diff --git a/OpenRA.Launcher/ConfigureModsDialog.Designer.cs b/OpenRA.Launcher/ConfigureModsDialog.Designer.cs index 8875492991..22d144e5aa 100644 --- a/OpenRA.Launcher/ConfigureModsDialog.Designer.cs +++ b/OpenRA.Launcher/ConfigureModsDialog.Designer.cs @@ -32,6 +32,7 @@ this.okButton = new System.Windows.Forms.Button(); this.installButton = new System.Windows.Forms.Button(); this.installModDialog = new System.Windows.Forms.OpenFileDialog(); + this.treeView1 = new System.Windows.Forms.TreeView(); this.SuspendLayout(); // // cancelButton @@ -71,11 +72,19 @@ this.installModDialog.Filter = "Zip files|*.zip"; this.installModDialog.RestoreDirectory = true; // + // treeView1 + // + this.treeView1.Location = new System.Drawing.Point(12, 12); + this.treeView1.Name = "treeView1"; + this.treeView1.Size = new System.Drawing.Size(175, 209); + this.treeView1.TabIndex = 3; + // // ConfigureModsDialog // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.ClientSize = new System.Drawing.Size(362, 262); + this.Controls.Add(this.treeView1); this.Controls.Add(this.installButton); this.Controls.Add(this.okButton); this.Controls.Add(this.cancelButton); @@ -95,5 +104,6 @@ private System.Windows.Forms.Button okButton; private System.Windows.Forms.Button installButton; private System.Windows.Forms.OpenFileDialog installModDialog; + private System.Windows.Forms.TreeView treeView1; } } \ No newline at end of file diff --git a/OpenRA.Launcher/ConfigureModsDialog.cs b/OpenRA.Launcher/ConfigureModsDialog.cs index ad7eb64519..37a7d7f243 100644 --- a/OpenRA.Launcher/ConfigureModsDialog.cs +++ b/OpenRA.Launcher/ConfigureModsDialog.cs @@ -9,29 +9,144 @@ using System.Windows.Forms; namespace OpenRA.Launcher { + struct Mod + { + public string Title; + public string Version; + public string Author; + public string Description; + public string Requires; + public bool Standalone; + } + public partial class ConfigureModsDialog : Form { - string[] currentMods; - string[] allMods; - public ConfigureModsDialog(string[] currentMods) + string[] activeMods; + Dictionary allMods; + public ConfigureModsDialog(string[] activeMods) { InitializeComponent(); Util.UacShield(installButton); - this.currentMods = currentMods; + this.activeMods = activeMods; + RefreshMods(); + } + + Mod GetMetadata(string mod) + { + var response = UtilityProgram.Call("-i", mod); + Mod m = new Mod(); + if (response.IsError) return m; + string[] lines = response.ResponseLines; + + + foreach (string line in lines) + { + string s = line.Trim(' ', '\r', '\n'); + int i = s.IndexOf(':'); + if (i + 2 > s.Length) continue; + string value = s.Substring(i + 2); + switch (s.Substring(0, i)) + { + case "Title": + m.Title = value; + break; + case "Version": + m.Version = value; + break; + case "Author": + m.Author = value; + break; + case "Description": + m.Description = value; + break; + case "Requires": + m.Requires = value; + break; + case "Standalone": + m.Standalone = bool.Parse(value); + break; + default: + break; + } + } + + return m; + } + + void RefreshMods() + { var response = UtilityProgram.Call("--list-mods"); + string[] mods; if (!response.IsError) - allMods = response.ResponseLines; + mods = response.ResponseLines; else throw new Exception(string.Format("Could not list mods: {0}", response.Response)); + + allMods = mods.ToDictionary(x => x, x => GetMetadata(x)); + + RefreshModTree(treeView1, allMods.Keys.ToArray()); } private void InstallMod(object sender, EventArgs e) { if (installModDialog.ShowDialog() != DialogResult.OK) return; - UtilityProgram.CallWithAdmin("--install-mods", "foo.zip"); + UtilityProgram.CallWithAdmin("--install-mods", installModDialog.FileName); + RefreshModTree(treeView1, allMods.Keys.ToArray()); + } + + void RefreshModTree(TreeView treeView, string[] modList) + { + Dictionary nodes; + nodes = modList.Where(x => allMods[x].Standalone).ToDictionary(x => x, x => new TreeNode(x)); + string[] rootMods = modList.Where(x => allMods[x].Standalone).ToArray(); + string[] remaining = modList.Except(nodes.Keys).ToArray(); + + while (remaining.Length > 0) + { + bool progress = false; + List toRemove = new List(); + foreach (string s in remaining) + { + var n = new TreeNode(s); + if (allMods[s].Requires == null) continue; + if (!nodes.ContainsKey(allMods[s].Requires)) continue; + nodes[allMods[s].Requires].Nodes.Add(n); + nodes.Add(s, n); + toRemove.Add(s); + progress = true; + } + + if (!progress) + break; + remaining = remaining.Except(toRemove).ToArray(); + } + + foreach (string s in rootMods) + treeView.Nodes.Add(nodes[s]); + + if (remaining.Length > 0) + { + var n = new TreeNode(""); + n.ForeColor = SystemColors.GrayText; + var m = new TreeNode(""); + m.ForeColor = SystemColors.GrayText; + + foreach (var s in remaining) + { + if (allMods[s].Requires == null) + n.Nodes.Add(new TreeNode(s) { ForeColor = SystemColors.GrayText }); + else if (!nodes.ContainsKey(allMods[s].Requires)) + m.Nodes.Add(new TreeNode(s) { ForeColor = SystemColors.GrayText }); + } + + treeView.Nodes.Add(n); + treeView.Nodes.Add(m); + } + + treeView.Invalidate(); } } } diff --git a/OpenRA.Launcher/MainForm.cs b/OpenRA.Launcher/MainForm.cs index 8db88a9ce8..06cb431cca 100644 --- a/OpenRA.Launcher/MainForm.cs +++ b/OpenRA.Launcher/MainForm.cs @@ -21,7 +21,7 @@ namespace OpenRA.Launcher var response = UtilityProgram.Call("--settings-value", configPath, "Game.Mods"); if (response.IsError) - currentMods = new string[] { }; + currentMods = new string[] { "ra" }; else currentMods = response.Response.Split(',');