diff --git a/Wabbajack.Common/Extensions/RxExt.cs b/Wabbajack.Common/Extensions/RxExt.cs
index 25ac87b2..0018d3a8 100644
--- a/Wabbajack.Common/Extensions/RxExt.cs
+++ b/Wabbajack.Common/Extensions/RxExt.cs
@@ -60,6 +60,32 @@ namespace Wabbajack
.Switch();
}
+ ///
+ /// Convenience operator to subscribe to the source observable, only when a second "switch" observable is on.
+ /// When the switch is on, the source will be subscribed to, and its updates passed through.
+ /// When the switch is off, the subscription to the source observable will be stopped, and no signal will be published.
+ ///
+ /// Source observable to subscribe to if on
+ /// On/Off signal of whether to subscribe to source observable
+ /// Value to fire when switching off
+ /// Observable that publishes data from source, if the switch is on.
+ public static IObservable FilterSwitch(this IObservable source, IObservable filterSwitch, T valueWhenOff)
+ {
+ return filterSwitch
+ .DistinctUntilChanged()
+ .Select(on =>
+ {
+ if (on)
+ {
+ return source;
+ }
+ else
+ {
+ return Observable.Return(valueWhenOff);
+ }
+ })
+ .Switch();
+ }
/// Inspiration:
/// http://reactivex.io/documentation/operators/debounce.html
diff --git a/Wabbajack/Themes/Styles.xaml b/Wabbajack/Themes/Styles.xaml
index b9cb0511..e5ce7573 100644
--- a/Wabbajack/Themes/Styles.xaml
+++ b/Wabbajack/Themes/Styles.xaml
@@ -1,27 +1,29 @@
-
+
-
+
-
-
+
+
-
+
#121212
#292929
#414141
#3D3D3D
#424242
+ #394140
#666666
-
+
#EFEFEF
#BDBDBD
@@ -34,6 +36,7 @@
#BB86FC
#3700B3
#03DAC6
+ #0e8f83
#C7FC86
#868CFC
#F686FC
@@ -50,102 +53,103 @@
-
-
-
+
+
+
+
-
+
-
-
-
-
-
+
+
+
+
+
-
+
-
-
-
-
-
+
+
+
+
+
-
+
-
+
-
-
+
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
-
-
-
+
+
+
+
-
-
-
-
-
+
+
+
+
+
-
-
-
-
-
-
+
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+
-
-
+
+
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
M-0.7,5.2 L-2.2,6.7 3.6,12.6 9.5,6.7 8,5.2 3.6,9.6 z
M-2.2,10.9 L-0.7,12.4 3.7,8 8,12.4 9.5,10.9 3.7,5 z
@@ -158,40 +162,40 @@
M3.5445026,0 L7.0890052,7.0890053 L3.0459049E-09,7.0890053 z
M-0,6 L-0,8 8,8 8,-0 6,-0 6,6 z
M5,-0 L9,5 1,5 z
-
-
+
+
-
+
-
+
@@ -240,138 +244,149 @@
-
+
-
+
-
-
+
-
+
@@ -960,57 +1066,62 @@
-
+
-
+
-
+
-
+
+
+
+
+
+
-
-
+
+
+
-
-
+
+
+
-
-
+
+
@@ -1297,53 +1457,57 @@
-
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
-
+
+
-
-
-
-
-
-
+
+
+
+
+
+
-
-
-
+
+
+
-
-
+
+
-
+
-
-
+
+
-
-
-
+
+
+
-
-
+
+
-
-
-
-
+
-
-
-
+
+
+
-
+
-
-
+
+
-
@@ -2491,170 +2810,194 @@
-
+
-
+
-
-
+
+
-
-
-
+
+
+
-
-
-
+
+
+
-
+
-
+
-
-
+
+
-
-
-
+
+
+
-
+
-
-
-
+
+
+
-
+
-
-
+
+
-
-
-
+
+
+
-
+
-
-
+
+
-
+
-
-
-
-
-
-
+
+
+
+
+
+
-
-
-
+
+
+
-
-
-
+
+
+
-
+
-
-
+
+
-
-
+
+
-
+
@@ -2663,113 +3006,118 @@
-
+
-
+
-
-
+
+
-
-
-
+
+
+
-
-
-
-
+
+
+
+
-
-
+
+
-
-
-
+
+
+
-
-
+
+
-
-
+
+
-
-
-
+
+
+
-
-
-
-
+
+
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
+
+
+
+
+
diff --git a/Wabbajack/View Models/Compilers/MO2CompilerVM.cs b/Wabbajack/View Models/Compilers/MO2CompilerVM.cs
index 296ab020..cd34cfc1 100644
--- a/Wabbajack/View Models/Compilers/MO2CompilerVM.cs
+++ b/Wabbajack/View Models/Compilers/MO2CompilerVM.cs
@@ -43,13 +43,13 @@ namespace Wabbajack
{
this.ModlistLocation = new FilePickerVM()
{
- DoExistsCheck = true,
+ ExistCheckOption = FilePickerVM.ExistCheckOptions.On,
PathType = FilePickerVM.PathTypeOptions.File,
PromptTitle = "Select Modlist"
};
this.DownloadLocation = new FilePickerVM()
{
- DoExistsCheck = true,
+ ExistCheckOption = FilePickerVM.ExistCheckOptions.On,
PathType = FilePickerVM.PathTypeOptions.Folder,
PromptTitle = "Select Download Location",
};
diff --git a/Wabbajack/View Models/Compilers/ModlistSettingsEditorVM.cs b/Wabbajack/View Models/Compilers/ModlistSettingsEditorVM.cs
index 42066044..a6bc955d 100644
--- a/Wabbajack/View Models/Compilers/ModlistSettingsEditorVM.cs
+++ b/Wabbajack/View Models/Compilers/ModlistSettingsEditorVM.cs
@@ -36,7 +36,7 @@ namespace Wabbajack
this.settings = settings;
this.ImagePath = new FilePickerVM()
{
- DoExistsCheck = false,
+ ExistCheckOption = FilePickerVM.ExistCheckOptions.IfNotEmpty,
PathType = FilePickerVM.PathTypeOptions.File,
Filters =
{
@@ -46,7 +46,7 @@ namespace Wabbajack
this.ReadMeText = new FilePickerVM()
{
PathType = FilePickerVM.PathTypeOptions.File,
- DoExistsCheck = false,
+ ExistCheckOption = FilePickerVM.ExistCheckOptions.IfNotEmpty,
};
}
diff --git a/Wabbajack/View Models/Compilers/VortexCompilerVM.cs b/Wabbajack/View Models/Compilers/VortexCompilerVM.cs
index 03bf20d6..94dc23e7 100644
--- a/Wabbajack/View Models/Compilers/VortexCompilerVM.cs
+++ b/Wabbajack/View Models/Compilers/VortexCompilerVM.cs
@@ -56,19 +56,19 @@ namespace Wabbajack
{
this.GameLocation = new FilePickerVM()
{
- DoExistsCheck = true,
+ ExistCheckOption = FilePickerVM.ExistCheckOptions.On,
PathType = FilePickerVM.PathTypeOptions.Folder,
PromptTitle = "Select Game Folder Location"
};
this.DownloadsLocation = new FilePickerVM()
{
- DoExistsCheck = true,
+ ExistCheckOption = FilePickerVM.ExistCheckOptions.On,
PathType = FilePickerVM.PathTypeOptions.Folder,
PromptTitle = "Select Downloads Folder"
};
this.StagingLocation = new FilePickerVM()
{
- DoExistsCheck = true,
+ ExistCheckOption = FilePickerVM.ExistCheckOptions.On,
PathType = FilePickerVM.PathTypeOptions.Folder,
PromptTitle = "Select Staging Folder"
};
diff --git a/Wabbajack/View Models/FilePickerVM.cs b/Wabbajack/View Models/FilePickerVM.cs
index c216cdb7..3e2fa7aa 100644
--- a/Wabbajack/View Models/FilePickerVM.cs
+++ b/Wabbajack/View Models/FilePickerVM.cs
@@ -23,6 +23,13 @@ namespace Wabbajack
Folder
}
+ public enum ExistCheckOptions
+ {
+ Off,
+ IfNotEmpty,
+ On
+ }
+
public object Parent { get; }
[Reactive]
@@ -38,7 +45,7 @@ namespace Wabbajack
public PathTypeOptions PathType { get; set; }
[Reactive]
- public bool DoExistsCheck { get; set; }
+ public ExistCheckOptions ExistCheckOption { get; set; }
[Reactive]
public IObservable AdditionalError { get; set; }
@@ -63,28 +70,60 @@ namespace Wabbajack
this.SetTargetPathCommand = ConstructTypicalPickerCommand();
// Check that file exists
- this._Exists = Observable.Interval(TimeSpan.FromSeconds(3))
- .FilterSwitch(
- Observable.CombineLatest(
- this.WhenAny(x => x.PathType),
- this.WhenAny(x => x.DoExistsCheck),
- resultSelector: (type, doExists) => type != PathTypeOptions.Off && doExists))
- .Unit()
- // Also do it when fields change
- .Merge(this.WhenAny(x => x.PathType).Unit())
- .Merge(this.WhenAny(x => x.DoExistsCheck).Unit())
- .CombineLatest(
- this.WhenAny(x => x.DoExistsCheck),
- this.WhenAny(x => x.PathType),
- this.WhenAny(x => x.TargetPath)
+
+ var existsCheckTuple = Observable.CombineLatest(
+ this.WhenAny(x => x.ExistCheckOption),
+ this.WhenAny(x => x.PathType),
+ this.WhenAny(x => x.TargetPath)
// Dont want to debounce the initial value, because we know it's null
.Skip(1)
- .Debounce(TimeSpan.FromMilliseconds(200)),
- resultSelector: (_, DoExists, Type, Path) => (DoExists, Type, Path))
+ .Debounce(TimeSpan.FromMilliseconds(200))
+ .StartWith(default(string)),
+ resultSelector: (ExistsOption, Type, Path) => (ExistsOption, Type, Path))
+ .Publish()
+ .RefCount();
+
+ this._Exists = Observable.Interval(TimeSpan.FromSeconds(3))
+ // Only check exists on timer if desired
+ .FilterSwitch(existsCheckTuple
+ .Select(t =>
+ {
+ // Don't do exists type if we don't know what path type we're tracking
+ if (t.Type == PathTypeOptions.Off) return false;
+ switch (t.ExistsOption)
+ {
+ case ExistCheckOptions.Off:
+ return false;
+ case ExistCheckOptions.IfNotEmpty:
+ return !string.IsNullOrWhiteSpace(t.Path);
+ case ExistCheckOptions.On:
+ return true;
+ default:
+ throw new NotImplementedException();
+ }
+ }))
+ .Unit()
+ // Also check though, when fields change
+ .Merge(this.WhenAny(x => x.PathType).Unit())
+ .Merge(this.WhenAny(x => x.ExistCheckOption).Unit())
+ .Merge(this.WhenAny(x => x.TargetPath).Unit())
+ // Signaled to check, get latest params for actual use
+ .CombineLatest(existsCheckTuple,
+ resultSelector: (_, tuple) => tuple)
// Refresh exists
.Select(t =>
{
- if (!t.DoExists) return true;
+ switch (t.ExistsOption)
+ {
+ case ExistCheckOptions.IfNotEmpty:
+ if (string.IsNullOrWhiteSpace(t.Path)) return true;
+ break;
+ case ExistCheckOptions.On:
+ break;
+ case ExistCheckOptions.Off:
+ default:
+ return true;
+ }
switch (t.Type)
{
case PathTypeOptions.Either:
diff --git a/Wabbajack/View Models/InstallerVM.cs b/Wabbajack/View Models/InstallerVM.cs
index 1f62ded0..1bc4e49a 100644
--- a/Wabbajack/View Models/InstallerVM.cs
+++ b/Wabbajack/View Models/InstallerVM.cs
@@ -99,7 +99,7 @@ namespace Wabbajack
this.Location = new FilePickerVM()
{
- DoExistsCheck = false,
+ ExistCheckOption = FilePickerVM.ExistCheckOptions.Off,
PathType = FilePickerVM.PathTypeOptions.Folder,
PromptTitle = "Select Installation Directory",
};
@@ -107,7 +107,7 @@ namespace Wabbajack
.Select(x => Utils.IsDirectoryPathValid(x));
this.DownloadLocation = new FilePickerVM()
{
- DoExistsCheck = false,
+ ExistCheckOption = FilePickerVM.ExistCheckOptions.Off,
PathType = FilePickerVM.PathTypeOptions.Folder,
PromptTitle = "Select a location for MO2 downloads",
};
diff --git a/Wabbajack/Views/Common/DetailImageView.xaml b/Wabbajack/Views/Common/DetailImageView.xaml
index c5e8a526..38280b2c 100644
--- a/Wabbajack/Views/Common/DetailImageView.xaml
+++ b/Wabbajack/Views/Common/DetailImageView.xaml
@@ -1,4 +1,4 @@
-
+ TextWrapping="WrapWithOverflow"
+ Visibility="{Binding ShowTitle, Mode=OneWay, RelativeSource={RelativeSource AncestorType={x:Type UserControl}}, Converter={StaticResource bool2VisibilityHiddenConverter}}">
@@ -113,7 +114,8 @@
FontSize="30"
FontWeight="Bold"
Style="{StaticResource BackgroundBlurStyle}"
- TextWrapping="WrapWithOverflow">
+ TextWrapping="WrapWithOverflow"
+ Visibility="{Binding ShowAuthor, Mode=OneWay, RelativeSource={RelativeSource AncestorType={x:Type UserControl}}, Converter={StaticResource bool2VisibilityHiddenConverter}}">
@@ -130,7 +132,8 @@
FontSize="65"
FontWeight="Bold"
Text="{Binding Title, Mode=OneWay, RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}"
- TextWrapping="WrapWithOverflow">
+ TextWrapping="WrapWithOverflow"
+ Visibility="{Binding ShowTitle, Mode=OneWay, RelativeSource={RelativeSource AncestorType={x:Type UserControl}}, Converter={StaticResource bool2VisibilityHiddenConverter}}">
@@ -142,7 +145,8 @@
FontFamily="Lucida Sans"
FontSize="30"
FontWeight="Bold"
- TextWrapping="Wrap">
+ TextWrapping="Wrap"
+ Visibility="{Binding ShowAuthor, Mode=OneWay, RelativeSource={RelativeSource AncestorType={x:Type UserControl}}, Converter={StaticResource bool2VisibilityHiddenConverter}}">
@@ -163,7 +167,8 @@
Style="{StaticResource BackgroundBlurStyle}"
Text="{Binding Description, Mode=OneWay, RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}"
TextAlignment="Right"
- TextWrapping="Wrap">
+ TextWrapping="Wrap"
+ Visibility="{Binding ShowDescription, Mode=OneWay, RelativeSource={RelativeSource AncestorType={x:Type UserControl}}, Converter={StaticResource bool2VisibilityHiddenConverter}}">
@@ -179,7 +184,8 @@
FontSize="16"
Text="{Binding Description, Mode=OneWay, RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}"
TextAlignment="Right"
- TextWrapping="Wrap">
+ TextWrapping="Wrap"
+ Visibility="{Binding ShowDescription, Mode=OneWay, RelativeSource={RelativeSource AncestorType={x:Type UserControl}}, Converter={StaticResource bool2VisibilityHiddenConverter}}">
@@ -192,4 +198,4 @@
Grid.ColumnSpan="2"
Fill="Transparent" />
-
+
diff --git a/Wabbajack/Views/Common/DetailImageView.xaml.cs b/Wabbajack/Views/Common/DetailImageView.xaml.cs
index e1094ede..4e8c2d9e 100644
--- a/Wabbajack/Views/Common/DetailImageView.xaml.cs
+++ b/Wabbajack/Views/Common/DetailImageView.xaml.cs
@@ -1,6 +1,8 @@
-using System;
+using ReactiveUI;
+using System;
using System.Collections.Generic;
using System.Linq;
+using System.Reactive.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
@@ -18,7 +20,7 @@ namespace Wabbajack
///
/// Interaction logic for DetailImageView.xaml
///
- public partial class DetailImageView : UserControl
+ public partial class DetailImageView : UserControlRx
{
public ImageSource Image
{
@@ -42,7 +44,7 @@ namespace Wabbajack
set => SetValue(TitleProperty, value);
}
public static readonly DependencyProperty TitleProperty = DependencyProperty.Register(nameof(Title), typeof(string), typeof(DetailImageView),
- new FrameworkPropertyMetadata(default(string), FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));
+ new FrameworkPropertyMetadata(default(string), FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, WireNotifyPropertyChanged));
public string Author
{
@@ -50,7 +52,7 @@ namespace Wabbajack
set => SetValue(AuthorProperty, value);
}
public static readonly DependencyProperty AuthorProperty = DependencyProperty.Register(nameof(Author), typeof(string), typeof(DetailImageView),
- new FrameworkPropertyMetadata(default(string), FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));
+ new FrameworkPropertyMetadata(default(string), FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, WireNotifyPropertyChanged));
public string Description
{
@@ -58,11 +60,32 @@ namespace Wabbajack
set => SetValue(DescriptionProperty, value);
}
public static readonly DependencyProperty DescriptionProperty = DependencyProperty.Register(nameof(Description), typeof(string), typeof(DetailImageView),
- new FrameworkPropertyMetadata(default(string), FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));
+ new FrameworkPropertyMetadata(default(string), FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, WireNotifyPropertyChanged));
+
+ private readonly ObservableAsPropertyHelper _ShowAuthor;
+ public bool ShowAuthor => _ShowAuthor.Value;
+
+ private readonly ObservableAsPropertyHelper _ShowDescription;
+ public bool ShowDescription => _ShowDescription.Value;
+
+ private readonly ObservableAsPropertyHelper _ShowTitle;
+ public bool ShowTitle => _ShowTitle.Value;
public DetailImageView()
{
InitializeComponent();
+
+ this._ShowAuthor = this.WhenAny(x => x.Author)
+ .Select(x => !string.IsNullOrWhiteSpace(x))
+ .ToProperty(this, nameof(this.ShowAuthor));
+
+ this._ShowDescription = this.WhenAny(x => x.Description)
+ .Select(x => !string.IsNullOrWhiteSpace(x))
+ .ToProperty(this, nameof(this.ShowDescription));
+
+ this._ShowTitle = this.WhenAny(x => x.Title)
+ .Select(x => !string.IsNullOrWhiteSpace(x))
+ .ToProperty(this, nameof(this.ShowTitle));
}
}
}
diff --git a/Wabbajack/Views/Common/FilePicker.xaml b/Wabbajack/Views/Common/FilePicker.xaml
index 17bd62f1..a254727b 100644
--- a/Wabbajack/Views/Common/FilePicker.xaml
+++ b/Wabbajack/Views/Common/FilePicker.xaml
@@ -10,36 +10,90 @@
d:DesignWidth="400"
BorderBrush="{StaticResource DarkBackgroundBrush}"
mc:Ignorable="d">
-
+
-
+
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Wabbajack/Views/Compilers/CompilerView.xaml b/Wabbajack/Views/Compilers/CompilerView.xaml
index 6916376e..89636ccc 100644
--- a/Wabbajack/Views/Compilers/CompilerView.xaml
+++ b/Wabbajack/Views/Compilers/CompilerView.xaml
@@ -85,7 +85,10 @@
-
diff --git a/Wabbajack/Views/Compilers/VortexCompilerConfigView.xaml b/Wabbajack/Views/Compilers/VortexCompilerConfigView.xaml
index 19b2a7bd..24649bd6 100644
--- a/Wabbajack/Views/Compilers/VortexCompilerConfigView.xaml
+++ b/Wabbajack/Views/Compilers/VortexCompilerConfigView.xaml
@@ -46,7 +46,7 @@
ToolTip="The game you wish to target">
-
+