diff --git a/OwlCore.Wpf/AbstractUI/Controls/AbstractUIGroupPresenter.cs b/OwlCore.Wpf/AbstractUI/Controls/AbstractUIGroupPresenter.cs
index aee2838..45840fb 100644
--- a/OwlCore.Wpf/AbstractUI/Controls/AbstractUIGroupPresenter.cs
+++ b/OwlCore.Wpf/AbstractUI/Controls/AbstractUIGroupPresenter.cs
@@ -1,7 +1,6 @@
using System.Windows;
using System.Windows.Controls;
using OwlCore.AbstractUI.ViewModels;
-using OwlCore.AbstractUI.Models;
namespace OwlCore.Wpf.AbstractUI.Controls
{
@@ -16,7 +15,7 @@ namespace OwlCore.Wpf.AbstractUI.Controls
/// Backing property for .
///
public static readonly DependencyProperty ViewModelProperty =
- DependencyProperty.Register(nameof(ViewModel), typeof(AbstractUICollectionViewModel), typeof(AbstractUIGroupPresenter), new PropertyMetadata(null, (d, e) => ((AbstractUIGroupPresenter)d).OnViewModelChanged()));
+ DependencyProperty.Register(nameof(ViewModel), typeof(AbstractUICollectionViewModel), typeof(AbstractUIGroupPresenter), new PropertyMetadata(null));
///
/// Backing property for .
@@ -48,62 +47,6 @@ namespace OwlCore.Wpf.AbstractUI.Controls
public AbstractUIGroupPresenter()
{
this.DefaultStyleKey = typeof(AbstractUIGroupPresenter);
-
- AttachEvents();
- }
-
- private void AttachEvents()
- {
- Loaded += OnLoaded;
-
- DataContextChanged += OnDataContextChanged;
- }
-
- private void DetachEvents()
- {
- DataContextChanged -= OnDataContextChanged;
- }
-
- private void OnDataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
- {
- if (_dataContextBeingSet)
- return;
-
- _dataContextBeingSet = true;
-
- if (DataContext is AbstractUICollection elementGroup)
- ViewModel = new AbstractUICollectionViewModel(elementGroup);
-
- if (DataContext is AbstractUICollectionViewModel elementGroupViewModel)
- ViewModel = elementGroupViewModel;
-
- _dataContextBeingSet = false;
- }
-
- private void OnLoaded(object sender, RoutedEventArgs e)
- {
- Loaded -= OnLoaded;
- Unloaded += OnUnloaded;
- }
-
- private void OnUnloaded(object sender, RoutedEventArgs e)
- {
- Unloaded -= OnUnloaded;
-
- DetachEvents();
- }
-
- ///
- /// Raised when the changes.
- ///
- public void OnViewModelChanged()
- {
- if (_dataContextBeingSet)
- return;
-
- _dataContextBeingSet = true;
- DataContext = ViewModel;
- _dataContextBeingSet = false;
}
}
}
diff --git a/OwlCore.Wpf/AbstractUI/Themes/AbstractUIGroupPresenterStyle.xaml b/OwlCore.Wpf/AbstractUI/Themes/AbstractUIGroupPresenterStyle.xaml
index dcb65fa..f7ec8c3 100644
--- a/OwlCore.Wpf/AbstractUI/Themes/AbstractUIGroupPresenterStyle.xaml
+++ b/OwlCore.Wpf/AbstractUI/Themes/AbstractUIGroupPresenterStyle.xaml
@@ -85,6 +85,7 @@
diff --git a/ZuneModCore/Mod.cs b/ZuneModCore/Mod.cs
index f7692b4..9c6aaef 100644
--- a/ZuneModCore/Mod.cs
+++ b/ZuneModCore/Mod.cs
@@ -2,6 +2,7 @@
using System;
using System.Collections.Generic;
using System.IO;
+using System.Linq;
using System.Threading.Tasks;
using ZuneModCore.Mods;
@@ -9,20 +10,6 @@ namespace ZuneModCore
{
public abstract class Mod
{
- ///
- /// A list of all available mods
- ///
- public static readonly IReadOnlyList AvailableMods = new List
- {
- new FeaturesOverrideMod(),
- new VideoSyncMod(),
- new WebservicesMod(),
- new BackgroundImageMod(),
- new MbidLocatorMod(),
- }.AsReadOnly();
-
- public static string ZuneInstallDir { get; set; } = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), "Zune");
-
public abstract string Id { get; }
public abstract string Title { get; }
@@ -55,13 +42,71 @@ namespace ZuneModCore
{
get
{
- string dir = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "ZuneModCore", Id);
+ string dir = Path.Combine(ModManager.CoreStorageDir, Id);
// Create the directory just in case the consumer assumes the folder exists already
Directory.CreateDirectory(dir);
return dir;
}
}
- public abstract IReadOnlyList? DependentMods { get; }
+ public abstract IReadOnlyList? DependentMods { get; }
+
+ ///
+ /// Initializes any missing depedencies.
+ ///
+ public Task InitDependencies() => ForAllDependencies(async mod =>
+ {
+ bool isDepApplied = await mod.CheckApplied();
+ if (!isDepApplied)
+ await mod.Init();
+ });
+
+ ///
+ /// Applies any missing depedencies.
+ ///
+ ///
+ /// Make sure to call first.
+ ///
+ public Task ApplyDependencies() => ForAllDependencies(async mod =>
+ {
+ bool isDepApplied = await mod.CheckApplied();
+ if (!isDepApplied)
+ await mod.Apply();
+ });
+
+ public Task CheckApplied() => TrueForAllDependencies(mod => mod.CheckApplied());
+
+ private async Task ForAllDependencies(Func asyncAction)
+ {
+ // Check if there are any dependencies
+ if (DependentMods == null)
+ return;
+
+ foreach (var dep in DependentMods)
+ {
+ var depMod = ModManager.AvailableMods.First(m => m.Id == dep.Id);
+ if (depMod != null)
+ await asyncAction(depMod);
+ }
+ }
+
+ private async Task TrueForAllDependencies(Func> asyncAction)
+ {
+ // Check if there are any dependencies
+ if (DependentMods == null)
+ return true;
+
+ foreach (var dep in DependentMods)
+ {
+ var depMod = ModManager.AvailableMods.First(m => m.Id == dep.Id);
+ if (depMod != null)
+ if (!await asyncAction(depMod))
+ return false;
+ }
+
+ return true;
+ }
+
+ public override string ToString() => Title;
}
}
diff --git a/ZuneModCore/ModDependency.cs b/ZuneModCore/ModDependency.cs
new file mode 100644
index 0000000..a87ffaa
--- /dev/null
+++ b/ZuneModCore/ModDependency.cs
@@ -0,0 +1,31 @@
+using System;
+using System.Text.Json;
+using System.Text.Json.Serialization;
+using System.Threading.Tasks;
+
+namespace ZuneModCore
+{
+ public class ModDependency
+ {
+ public string Id { get; set; }
+
+ public ReleaseVersion Version { get; set; }
+
+ public ModDependency(string id, ReleaseVersion? version = null)
+ {
+ Id = id;
+ Version = version ?? ModManager.CurrentVersion;
+ }
+
+ ///
+ /// DO NOT USE DIRECTLY. This constructor is only for
+ /// JSON de/serialization.
+ ///
+ [Obsolete]
+ internal ModDependency() { }
+
+ public Task CheckStatus() => ModManager.CheckStatus(Id);
+
+ public override string ToString() => $"{Id} / {Version}";
+ }
+}
diff --git a/ZuneModCore/ModManager.cs b/ZuneModCore/ModManager.cs
new file mode 100644
index 0000000..c54c9c0
--- /dev/null
+++ b/ZuneModCore/ModManager.cs
@@ -0,0 +1,80 @@
+using CommunityToolkit.Diagnostics;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Text.Json;
+using System.Threading.Tasks;
+using ZuneModCore.Mods;
+
+namespace ZuneModCore
+{
+ public static class ModManager
+ {
+ ///
+ /// A list of all available mods.
+ ///
+ public static readonly IReadOnlyList AvailableMods = new List
+ {
+ new FeaturesOverrideMod(),
+ new VideoSyncMod(),
+ new WebservicesMod(),
+ new BackgroundImageMod(),
+ new MbidLocatorMod(),
+ };
+
+ public static string ZuneInstallDir { get; set; } = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), "Zune");
+
+ public static readonly ReleaseVersion CurrentVersion = new(2021, 12, 30, 0, Phase.Alpha);
+
+ internal static readonly string CoreStorageDir = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "ZuneModCore");
+
+ private static readonly string CoreStatusFile = Path.Combine(CoreStorageDir, "ModStatus.json");
+
+ ///
+ /// Marks the specified mod as applied in the status file.
+ ///
+ internal static Task MarkApplied(string modId) => MarkStatus(modId, true);
+
+ ///
+ /// Marks the specified mod as reset in the status file.
+ ///
+ internal static Task MarkReset(string modId) => MarkStatus(modId, false);
+
+ ///
+ /// Sets the status of the specified mod in the status file.
+ ///
+ private static async Task MarkStatus(string modId, bool status)
+ {
+ using var stream = File.Open(CoreStatusFile, FileMode.OpenOrCreate);
+ var model = await JsonSerializer.DeserializeAsync(stream);
+ Guard.IsNotNull(model, nameof(model));
+
+ bool curStatus = model.InstalledMods.ContainsKey(modId);
+ if (curStatus && !status)
+ {
+ model.InstalledMods.Remove(modId);
+ }
+ else if (!curStatus && status)
+ {
+ model.InstalledMods.Add(modId, CurrentVersion);
+ }
+
+ await JsonSerializer.SerializeAsync(stream, model);
+ }
+
+ ///
+ /// Gets the status of the specified mod from the status file.
+ ///
+ internal static async Task CheckStatus(string modId)
+ {
+ if (!File.Exists(CoreStatusFile))
+ return false;
+
+ using var stream = File.OpenRead(CoreStatusFile);
+ var model = await JsonSerializer.DeserializeAsync(stream);
+ Guard.IsNotNull(model, nameof(model));
+
+ return model.InstalledMods.ContainsKey(modId);
+ }
+ }
+}
diff --git a/ZuneModCore/Mods/BackgroundImageMod.cs b/ZuneModCore/Mods/BackgroundImageMod.cs
index e8df83d..accaa6c 100644
--- a/ZuneModCore/Mods/BackgroundImageMod.cs
+++ b/ZuneModCore/Mods/BackgroundImageMod.cs
@@ -32,7 +32,7 @@ namespace ZuneModCore.Mods
};
}
- public override IReadOnlyList? DependentMods => null;
+ public override IReadOnlyList? DependentMods => null;
public override async Task Apply()
{
@@ -43,7 +43,7 @@ namespace ZuneModCore.Mods
return $"The file '{bgimgInfo.FullName}' does not exist.";
}
- FileInfo zsrDllInfo = new(Path.Combine(ZuneInstallDir, "ZuneShellResources.dll"));
+ FileInfo zsrDllInfo = new(Path.Combine(ModManager.ZuneInstallDir, "ZuneShellResources.dll"));
if (!zsrDllInfo.Exists)
{
return $"The file '{zsrDllInfo.FullName}' does not exist.";
@@ -120,7 +120,7 @@ namespace ZuneModCore.Mods
{
// Copy backup to application folder
File.Copy(Path.Combine(StorageDirectory, "ZuneShellResources.original.dll"),
- Path.Combine(ZuneInstallDir, "ZuneShellResources.dll"), true);
+ Path.Combine(ModManager.ZuneInstallDir, "ZuneShellResources.dll"), true);
return Task.FromResult(null);
}
diff --git a/ZuneModCore/Mods/FeaturesOverrideMod.cs b/ZuneModCore/Mods/FeaturesOverrideMod.cs
index 72e5542..c9da497 100644
--- a/ZuneModCore/Mods/FeaturesOverrideMod.cs
+++ b/ZuneModCore/Mods/FeaturesOverrideMod.cs
@@ -56,7 +56,7 @@ namespace ZuneModCore.Mods
};
}
- public override IReadOnlyList? DependentMods => null;
+ public override IReadOnlyList? DependentMods => null;
public override Task Init()
{
diff --git a/ZuneModCore/Mods/MbidLocatorMod.cs b/ZuneModCore/Mods/MbidLocatorMod.cs
index 8aada30..e580c59 100644
--- a/ZuneModCore/Mods/MbidLocatorMod.cs
+++ b/ZuneModCore/Mods/MbidLocatorMod.cs
@@ -37,7 +37,7 @@ namespace ZuneModCore.Mods
};
}
- public override IReadOnlyList? DependentMods => null;
+ public override IReadOnlyList? DependentMods => null;
public override async Task Apply()
{
diff --git a/ZuneModCore/Mods/VideoSyncMod.cs b/ZuneModCore/Mods/VideoSyncMod.cs
index b651773..da549e1 100644
--- a/ZuneModCore/Mods/VideoSyncMod.cs
+++ b/ZuneModCore/Mods/VideoSyncMod.cs
@@ -71,6 +71,6 @@ namespace ZuneModCore.Mods
}
}
- public override IReadOnlyList? DependentMods => null;
+ public override IReadOnlyList? DependentMods => null;
}
}
diff --git a/ZuneModCore/Mods/WebservicesMod.cs b/ZuneModCore/Mods/WebservicesMod.cs
index 4513915..3a508f4 100644
--- a/ZuneModCore/Mods/WebservicesMod.cs
+++ b/ZuneModCore/Mods/WebservicesMod.cs
@@ -76,7 +76,10 @@ namespace ZuneModCore.Mods
};
}
- public override IReadOnlyList? DependentMods => null;
+ public override IReadOnlyList? DependentMods => new List
+ {
+ new(nameof(FeaturesOverrideMod))
+ };
public override Task Init()
{
@@ -90,7 +93,7 @@ namespace ZuneModCore.Mods
public override async Task Apply()
{
// Verify that ZuneServices.dll exists
- FileInfo zsDllInfo = new(Path.Combine(ZuneInstallDir, "ZuneService.dll"));
+ FileInfo zsDllInfo = new(Path.Combine(ModManager.ZuneInstallDir, "ZuneService.dll"));
if (!zsDllInfo.Exists)
{
return $"The file '{zsDllInfo.FullName}' does not exist.";
@@ -182,7 +185,7 @@ namespace ZuneModCore.Mods
public override async Task Reset()
{
- string zsDllPath = Path.Combine(ZuneInstallDir, "ZuneService.dll");
+ string zsDllPath = Path.Combine(ModManager.ZuneInstallDir, "ZuneService.dll");
try
{
// Copy backup to application folder
@@ -258,7 +261,7 @@ namespace ZuneModCore.Mods
}
}
- private async Task Ping(string url)
+ private static async Task Ping(string url)
{
try
{
diff --git a/ZuneModdingHelper/ReleaseVersion.cs b/ZuneModCore/ReleaseVersion.cs
similarity index 96%
rename from ZuneModdingHelper/ReleaseVersion.cs
rename to ZuneModCore/ReleaseVersion.cs
index 26dd726..e5c460c 100644
--- a/ZuneModdingHelper/ReleaseVersion.cs
+++ b/ZuneModCore/ReleaseVersion.cs
@@ -1,14 +1,13 @@
using CommunityToolkit.Diagnostics;
using System;
-using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
-using System.Linq;
using System.Runtime.CompilerServices;
-using System.Text;
-using System.Threading.Tasks;
+using System.Text.Json;
+using System.Text.Json.Serialization;
-namespace ZuneModdingHelper
+namespace ZuneModCore
{
+ [JsonConverter(typeof(ReleaseVersionJsonConverter))]
public sealed class ReleaseVersion : ICloneable, IComparable, IComparable, IEquatable
{
///
@@ -481,4 +480,17 @@ namespace ZuneModdingHelper
ReleaseCandidate,
Production
}
+
+ internal class ReleaseVersionJsonConverter : JsonConverter
+ {
+ public override ReleaseVersion Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
+ {
+ return ReleaseVersion.Parse(reader.GetString()!);
+ }
+
+ public override void Write(Utf8JsonWriter writer, ReleaseVersion value, JsonSerializerOptions options)
+ {
+ writer.WriteStringValue(value.ToString());
+ }
+ }
}
diff --git a/ZuneModCore/StatusModel.cs b/ZuneModCore/StatusModel.cs
new file mode 100644
index 0000000..9db0cdc
--- /dev/null
+++ b/ZuneModCore/StatusModel.cs
@@ -0,0 +1,20 @@
+using System.Collections.Generic;
+
+namespace ZuneModCore
+{
+ internal class StatusModel
+ {
+ ///
+ /// The version of ZuneModCore that created this model.
+ ///
+ public ReleaseVersion Version { get; set; }
+
+ ///
+ /// A list of mods that are currently installed.
+ ///
+ /// Key is mod ID and Value is installed version.
+ ///
+ ///
+ public Dictionary InstalledMods { get; set; }
+ }
+}
diff --git a/ZuneModCore/ZuneModCore.csproj b/ZuneModCore/ZuneModCore.csproj
index 4f3daa8..22e89bf 100644
--- a/ZuneModCore/ZuneModCore.csproj
+++ b/ZuneModCore/ZuneModCore.csproj
@@ -8,6 +8,7 @@
+
diff --git a/ZuneModdingHelper/AbstractUIGroupDialog.xaml.cs b/ZuneModdingHelper/AbstractUIGroupDialog.xaml.cs
deleted file mode 100644
index b2aa71a..0000000
--- a/ZuneModdingHelper/AbstractUIGroupDialog.xaml.cs
+++ /dev/null
@@ -1,43 +0,0 @@
-using MahApps.Metro.Controls;
-using OwlCore.AbstractUI.Models;
-using OwlCore.AbstractUI.ViewModels;
-using OwlCore.Wpf.AbstractUI.Controls;
-using System.Windows;
-
-namespace ZuneModdingHelper
-{
- ///
- /// Interaction logic for AbstractUIGroupDialog.xaml
- ///
- public partial class AbstractUIGroupDialog : MetroWindow
- {
- public AbstractUIGroupDialog(AbstractUICollectionViewModel viewModel)
- {
- ViewModel = viewModel;
- DataContext = ViewModel;
- InitializeComponent();
- }
- public AbstractUIGroupDialog(AbstractUICollection group) : this(new AbstractUICollectionViewModel(group))
- {
-
- }
-
- private void OptionsUINextButton_Click(object sender, RoutedEventArgs e) => Finish(true);
-
- private void OptionsUICancelButton_Click(object sender, RoutedEventArgs e) => Finish(false);
-
- private void Finish(bool result)
- {
- DialogResult = result;
- Close();
- }
-
- public AbstractUICollectionViewModel ViewModel
- {
- get => (AbstractUICollectionViewModel)GetValue(ViewModelProperty);
- set => SetValue(ViewModelProperty, value);
- }
- public static readonly DependencyProperty ViewModelProperty = DependencyProperty.Register(
- nameof(ViewModel), typeof(AbstractUICollectionViewModel), typeof(AbstractUIGroupDialog));
- }
-}
diff --git a/ZuneModdingHelper/App.xaml.cs b/ZuneModdingHelper/App.xaml.cs
index 74feb34..8f69b9e 100644
--- a/ZuneModdingHelper/App.xaml.cs
+++ b/ZuneModdingHelper/App.xaml.cs
@@ -2,6 +2,7 @@
using Microsoft.AppCenter;
using Microsoft.AppCenter.Analytics;
using Microsoft.AppCenter.Crashes;
+using ZuneModCore;
namespace ZuneModdingHelper
{
@@ -12,7 +13,7 @@ namespace ZuneModdingHelper
{
public const string Title = "Zune Modding Helper";
- public static readonly ReleaseVersion Version = new(2021, 12, 30, 0, Phase.Alpha);
+ public static readonly ReleaseVersion Version = ModManager.CurrentVersion;
public static readonly string VersionStr = Version.ToString();
public const string DonateLink = "http://josh.askharoun.com/donate";
diff --git a/ZuneModdingHelper/MainWindow.xaml.cs b/ZuneModdingHelper/MainWindow.xaml.cs
index 800b929..5c01a6c 100644
--- a/ZuneModdingHelper/MainWindow.xaml.cs
+++ b/ZuneModdingHelper/MainWindow.xaml.cs
@@ -41,8 +41,8 @@ namespace ZuneModdingHelper
ThemeManager.Current.ThemeSyncMode = ThemeSyncMode.SyncWithAppMode;
ThemeManager.Current.SyncTheme();
- ModList.ItemsSource = Mod.AvailableMods;
- ZuneInstallDirBox.Text = Mod.ZuneInstallDir;
+ ModList.ItemsSource = ModManager.AvailableMods;
+ ZuneInstallDirBox.Text = ModManager.ZuneInstallDir;
}
private async System.Threading.Tasks.Task RunOnUI(Action action) => await Dispatcher.BeginInvoke(action);
@@ -51,7 +51,7 @@ namespace ZuneModdingHelper
{
// Show a warning if Zune is running
Process[] procs = Process.GetProcessesByName("Zune");
- string zuneExePath = Path.Combine(Mod.ZuneInstallDir, "Zune.exe");
+ string zuneExePath = Path.Combine(ModManager.ZuneInstallDir, "Zune.exe");
if (procs.Length > 0 && procs.Any(p => p.MainModule.FileName == zuneExePath))
{
await this.ShowMessageAsync(
@@ -65,7 +65,7 @@ namespace ZuneModdingHelper
{
var progDialog = await this.ShowProgressAsync("Getting ready...", "Preparing to apply mod", settings: defaultMetroDialogSettings);
Mod mod = (Mod)((FrameworkElement)sender).DataContext;
- Mod.ZuneInstallDir = ZuneInstallDirBox.Text;
+ ModManager.ZuneInstallDir = ZuneInstallDirBox.Text;
progDialog.Maximum = 3;
int numCompleted = 0;
@@ -80,15 +80,14 @@ namespace ZuneModdingHelper
progDialog.SetMessage("Awaiting options...");
if (mod.OptionsUI != null)
{
- var optionsDialog = new AbstractUIGroupDialog(mod.OptionsUI);
- optionsDialog.Title = optionsDialog.Title + " | " + mod.Title;
+ var optionsDialog = new OptionsUIDialog(mod);
bool? optionsResult = optionsDialog.ShowDialog();
if (!(optionsResult.HasValue && optionsResult.Value))
{
await progDialog.CloseAsync();
return;
}
- mod.OptionsUI = (AbstractUICollection)optionsDialog.ViewModel.Model;
+ mod.OptionsUI = (AbstractUICollection)optionsDialog.OptionsViewModel.Model;
}
progDialog.SetProgress(++numCompleted);
@@ -122,7 +121,7 @@ namespace ZuneModdingHelper
if (sender is FrameworkElement elem && elem.DataContext is Mod mod)
{
var progDialog = await this.ShowProgressAsync("Getting ready...", "Preparing to reset mod", settings: defaultMetroDialogSettings);
- Mod.ZuneInstallDir = ZuneInstallDirBox.Text;
+ ModManager.ZuneInstallDir = ZuneInstallDirBox.Text;
progDialog.Maximum = 2;
int numCompleted = 0;
@@ -279,7 +278,7 @@ namespace ZuneModdingHelper
CommonOpenFileDialog dialog = new()
{
IsFolderPicker = true,
- DefaultDirectory = Mod.ZuneInstallDir
+ DefaultDirectory = ModManager.ZuneInstallDir
};
CommonFileDialogResult result = dialog.ShowDialog();
if (result == CommonFileDialogResult.Ok)
diff --git a/ZuneModdingHelper/AbstractUIGroupDialog.xaml b/ZuneModdingHelper/OptionsUIDialog.xaml
similarity index 65%
rename from ZuneModdingHelper/AbstractUIGroupDialog.xaml
rename to ZuneModdingHelper/OptionsUIDialog.xaml
index 0fc3e2d..f88138f 100644
--- a/ZuneModdingHelper/AbstractUIGroupDialog.xaml
+++ b/ZuneModdingHelper/OptionsUIDialog.xaml
@@ -1,14 +1,14 @@
-
+
@@ -24,8 +24,13 @@
-
+
+
+
+
+
diff --git a/ZuneModdingHelper/OptionsUIDialog.xaml.cs b/ZuneModdingHelper/OptionsUIDialog.xaml.cs
new file mode 100644
index 0000000..6ccb4e2
--- /dev/null
+++ b/ZuneModdingHelper/OptionsUIDialog.xaml.cs
@@ -0,0 +1,57 @@
+using MahApps.Metro.Controls;
+using OwlCore.AbstractUI.Models;
+using OwlCore.AbstractUI.ViewModels;
+using OwlCore.Wpf.AbstractUI.Controls;
+using System.Windows;
+using ZuneModCore;
+
+namespace ZuneModdingHelper
+{
+ ///
+ /// A dialog that displays the options and dependencies for the given .
+ ///
+ public partial class OptionsUIDialog : MetroWindow
+ {
+ public OptionsUIDialog(Mod mod)
+ {
+ InitializeComponent();
+
+ DataContext = this;
+ CurrentMod = mod;
+ if (CurrentMod.OptionsUI != null)
+ {
+ OptionsViewModel = new(CurrentMod.OptionsUI);
+ }
+
+ Title = "Options | " + CurrentMod.Title;
+ }
+
+ private void OptionsUINextButton_Click(object sender, RoutedEventArgs e) => Finish(true);
+
+ private void OptionsUICancelButton_Click(object sender, RoutedEventArgs e) => Finish(false);
+
+ private void Finish(bool result)
+ {
+ DialogResult = result;
+ Close();
+ }
+
+ public Mod CurrentMod
+ {
+ get => (Mod)GetValue(CurrentModProperty);
+ set => SetValue(CurrentModProperty, value);
+ }
+ public static readonly DependencyProperty CurrentModProperty = DependencyProperty.Register(
+ nameof(CurrentMod), typeof(Mod), typeof(OptionsUIDialog));
+
+ public AbstractUICollectionViewModel OptionsViewModel
+ {
+ get => (AbstractUICollectionViewModel)GetValue(OptionsViewModelProperty);
+ set => SetValue(OptionsViewModelProperty, value);
+ }
+ public static readonly DependencyProperty OptionsViewModelProperty = DependencyProperty.Register(
+ nameof(OptionsViewModel), typeof(AbstractUICollectionViewModel), typeof(OptionsUIDialog));
+
+ public bool HasOptions => CurrentMod.OptionsUI != null;
+ }
+}