mirror of
https://github.com/wabbajack-tools/wabbajack.git
synced 2024-08-30 18:42:17 +00:00
Merge pull request #139 from Noggog/hotfix-download-picker
Hotfix download picker
This commit is contained in:
commit
d947de193c
88
Wabbajack.Common/Error States/ErrorResponse.cs
Normal file
88
Wabbajack.Common/Error States/ErrorResponse.cs
Normal file
@ -0,0 +1,88 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Wabbajack
|
||||
{
|
||||
public struct ErrorResponse : IErrorResponse
|
||||
{
|
||||
public readonly static ErrorResponse Success = Succeed();
|
||||
public readonly static ErrorResponse Failure = new ErrorResponse();
|
||||
|
||||
public readonly bool Succeeded;
|
||||
public readonly Exception Exception;
|
||||
private readonly string _reason;
|
||||
|
||||
public bool Failed => !Succeeded;
|
||||
public string Reason
|
||||
{
|
||||
get
|
||||
{
|
||||
if (this.Exception != null)
|
||||
{
|
||||
return this.Exception.ToString();
|
||||
}
|
||||
return _reason;
|
||||
}
|
||||
}
|
||||
|
||||
bool IErrorResponse.Succeeded => this.Succeeded;
|
||||
Exception IErrorResponse.Exception => this.Exception;
|
||||
|
||||
private ErrorResponse(
|
||||
bool succeeded,
|
||||
string reason = null,
|
||||
Exception ex = null)
|
||||
{
|
||||
this.Succeeded = succeeded;
|
||||
this._reason = reason;
|
||||
this.Exception = ex;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"({(Succeeded ? "Success" : "Fail")}, {Reason})";
|
||||
}
|
||||
|
||||
#region Factories
|
||||
public static ErrorResponse Succeed()
|
||||
{
|
||||
return new ErrorResponse(true);
|
||||
}
|
||||
|
||||
public static ErrorResponse Succeed(string reason)
|
||||
{
|
||||
return new ErrorResponse(true, reason);
|
||||
}
|
||||
|
||||
public static ErrorResponse Fail(string reason)
|
||||
{
|
||||
return new ErrorResponse(false, reason: reason);
|
||||
}
|
||||
|
||||
public static ErrorResponse Fail(Exception ex)
|
||||
{
|
||||
return new ErrorResponse(false, ex: ex);
|
||||
}
|
||||
|
||||
public static ErrorResponse Fail()
|
||||
{
|
||||
return new ErrorResponse(false);
|
||||
}
|
||||
|
||||
public static ErrorResponse Create(bool successful, string reason = null)
|
||||
{
|
||||
return new ErrorResponse(successful, reason);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
||||
public interface IErrorResponse
|
||||
{
|
||||
bool Succeeded { get; }
|
||||
Exception Exception { get; }
|
||||
string Reason { get; }
|
||||
}
|
||||
}
|
137
Wabbajack.Common/Error States/GetResponse.cs
Normal file
137
Wabbajack.Common/Error States/GetResponse.cs
Normal file
@ -0,0 +1,137 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Wabbajack
|
||||
{
|
||||
public struct GetResponse<T> : IEquatable<GetResponse<T>>, IErrorResponse
|
||||
{
|
||||
public static readonly GetResponse<T> Failure = new GetResponse<T>();
|
||||
|
||||
public readonly T Value;
|
||||
public readonly bool Succeeded;
|
||||
public readonly Exception Exception;
|
||||
private readonly string _reason;
|
||||
|
||||
public bool Failed => !Succeeded;
|
||||
public string Reason
|
||||
{
|
||||
get
|
||||
{
|
||||
if (this.Exception != null)
|
||||
{
|
||||
return this.Exception.ToString();
|
||||
}
|
||||
return _reason;
|
||||
}
|
||||
}
|
||||
|
||||
bool IErrorResponse.Succeeded => this.Succeeded;
|
||||
Exception IErrorResponse.Exception => this.Exception;
|
||||
|
||||
private GetResponse(
|
||||
bool succeeded,
|
||||
T val = default(T),
|
||||
string reason = null,
|
||||
Exception ex = null)
|
||||
{
|
||||
this.Value = val;
|
||||
this.Succeeded = succeeded;
|
||||
this._reason = reason;
|
||||
this.Exception = ex;
|
||||
}
|
||||
|
||||
public bool Equals(GetResponse<T> other)
|
||||
{
|
||||
return this.Succeeded == other.Succeeded
|
||||
&& object.Equals(this.Value, other.Value);
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
if (!(obj is GetResponse<T> rhs)) return false;
|
||||
return Equals(rhs);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return HashHelper.GetHashCode(Value)
|
||||
.CombineHashCode(Succeeded.GetHashCode());
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"({(Succeeded ? "Success" : "Fail")}, {Value}, {Reason})";
|
||||
}
|
||||
|
||||
public GetResponse<R> BubbleFailure<R>()
|
||||
{
|
||||
return new GetResponse<R>(
|
||||
succeeded: false,
|
||||
reason: this._reason,
|
||||
ex: this.Exception);
|
||||
}
|
||||
|
||||
public GetResponse<R> Bubble<R>(Func<T, R> conv)
|
||||
{
|
||||
return new GetResponse<R>(
|
||||
succeeded: this.Succeeded,
|
||||
val: conv(this.Value),
|
||||
reason: this._reason,
|
||||
ex: this.Exception);
|
||||
}
|
||||
|
||||
public T EvaluateOrThrow()
|
||||
{
|
||||
if (this.Succeeded)
|
||||
{
|
||||
return this.Value;
|
||||
}
|
||||
throw new ArgumentException(this.Reason);
|
||||
}
|
||||
|
||||
#region Factories
|
||||
public static GetResponse<T> Succeed(T value)
|
||||
{
|
||||
return new GetResponse<T>(true, value);
|
||||
}
|
||||
|
||||
public static GetResponse<T> Succeed(T value, string reason)
|
||||
{
|
||||
return new GetResponse<T>(true, value, reason);
|
||||
}
|
||||
|
||||
public static GetResponse<T> Fail(string reason)
|
||||
{
|
||||
return new GetResponse<T>(false, reason: reason);
|
||||
}
|
||||
|
||||
public static GetResponse<T> Fail(T val, string reason)
|
||||
{
|
||||
return new GetResponse<T>(false, val, reason);
|
||||
}
|
||||
|
||||
public static GetResponse<T> Fail(Exception ex)
|
||||
{
|
||||
return new GetResponse<T>(false, ex: ex);
|
||||
}
|
||||
|
||||
public static GetResponse<T> Fail(T val, Exception ex)
|
||||
{
|
||||
return new GetResponse<T>(false, val, ex: ex);
|
||||
}
|
||||
|
||||
public static GetResponse<T> Fail(T val)
|
||||
{
|
||||
return new GetResponse<T>(false, val);
|
||||
}
|
||||
|
||||
public static GetResponse<T> Create(bool successful, T val = default(T), string reason = null)
|
||||
{
|
||||
return new GetResponse<T>(successful, val, reason);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
133
Wabbajack.Common/Extensions/HashHelper.cs
Normal file
133
Wabbajack.Common/Extensions/HashHelper.cs
Normal file
@ -0,0 +1,133 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
/*
|
||||
* Taken from: http://stackoverflow.com/questions/263400/what-is-the-best-algorithm-for-an-overridden-system-object-gethashcode
|
||||
*/
|
||||
namespace Wabbajack
|
||||
{
|
||||
public static class HashHelper
|
||||
{
|
||||
public static int GetHashCode<T1, T2>(T1 arg1, T2 arg2)
|
||||
{
|
||||
unchecked
|
||||
{
|
||||
return 31 * (arg1 == null ? 0 : arg1.GetHashCode())
|
||||
+ (arg2 == null ? 0 : arg2.GetHashCode());
|
||||
}
|
||||
}
|
||||
|
||||
public static int GetHashCode<T1, T2, T3>(T1 arg1, T2 arg2, T3 arg3)
|
||||
{
|
||||
unchecked
|
||||
{
|
||||
int hash = (arg1 == null ? 0 : arg1.GetHashCode());
|
||||
hash = 31 * hash + (arg2 == null ? 0 : arg2.GetHashCode());
|
||||
return 31 * hash + (arg3 == null ? 0 : arg3.GetHashCode());
|
||||
}
|
||||
}
|
||||
|
||||
public static int GetHashCode<T1, T2, T3, T4>(T1 arg1, T2 arg2, T3 arg3, T4 arg4)
|
||||
{
|
||||
unchecked
|
||||
{
|
||||
int hash = (arg1 == null ? 0 : arg1.GetHashCode());
|
||||
hash = 31 * hash + (arg2 == null ? 0 : arg2.GetHashCode());
|
||||
hash = 31 * hash + (arg3 == null ? 0 : arg3.GetHashCode());
|
||||
return 31 * hash + (arg4 == null ? 0 : arg4.GetHashCode());
|
||||
}
|
||||
}
|
||||
|
||||
public static int GetHashCode<T>(params T[] list)
|
||||
{
|
||||
unchecked
|
||||
{
|
||||
int hash = 0;
|
||||
if (list == null) return hash;
|
||||
for (int i = 0; i < list.Length; i++)
|
||||
{
|
||||
hash = 31 * hash + GetHashCode(list[i]);
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
}
|
||||
|
||||
public static int GetHashCode<T>(ReadOnlySpan<T> span)
|
||||
{
|
||||
unchecked
|
||||
{
|
||||
int hash = 0;
|
||||
if (span == null) return hash;
|
||||
for (int i = 0; i < span.Length; i++)
|
||||
{
|
||||
hash = 31 * hash + GetHashCode(span[i]);
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
}
|
||||
|
||||
public static int GetHashCode<T>(T t)
|
||||
{
|
||||
unchecked
|
||||
{
|
||||
return (t == null ? 0 : t.GetHashCode());
|
||||
}
|
||||
}
|
||||
|
||||
public static int GetHashCode<T>(IEnumerable<T> list)
|
||||
{
|
||||
unchecked
|
||||
{
|
||||
int hash = 0;
|
||||
foreach (var item in list)
|
||||
{
|
||||
hash = 31 * hash + (item == null ? 0 : item.GetHashCode());
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a hashcode for a collection for that the order of items
|
||||
/// does not matter.
|
||||
/// So {1, 2, 3} and {3, 2, 1} will get same hash code.
|
||||
/// </summary>
|
||||
public static int GetHashCode_OrderBlind<T>(
|
||||
IEnumerable<T> list)
|
||||
{
|
||||
unchecked
|
||||
{
|
||||
int hash = 0;
|
||||
int count = 0;
|
||||
foreach (var item in list)
|
||||
{
|
||||
hash += (item == null ? 0 : item.GetHashCode());
|
||||
count++;
|
||||
}
|
||||
return 31 * hash + count.GetHashCode();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Alternative way to get a hashcode is to use a fluent
|
||||
/// interface like this:<br />
|
||||
/// return 0.CombineHashCode(field1).CombineHashCode(field2).
|
||||
/// CombineHashCode(field3);
|
||||
/// </summary>
|
||||
public static int CombineHashCode<T>(this int hashCode, T arg)
|
||||
{
|
||||
unchecked
|
||||
{
|
||||
return CombineHashCode(hashCode, (arg == null ? 0 : arg.GetHashCode()));
|
||||
}
|
||||
}
|
||||
|
||||
public static int CombineHashCode(this int hashCode, int rhsHash)
|
||||
{
|
||||
unchecked
|
||||
{
|
||||
return 31 * hashCode + rhsHash;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -657,5 +657,56 @@ namespace Wabbajack.Common
|
||||
Status(s);
|
||||
Log(s);
|
||||
}
|
||||
|
||||
/// https://stackoverflow.com/questions/422090/in-c-sharp-check-that-filename-is-possibly-valid-not-that-it-exists
|
||||
public static IErrorResponse IsFilePathValid(string path)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(path))
|
||||
{
|
||||
return ErrorResponse.Fail("Path was empty.");
|
||||
}
|
||||
try
|
||||
{
|
||||
var fi = new System.IO.FileInfo(path);
|
||||
}
|
||||
catch (ArgumentException ex)
|
||||
{
|
||||
return ErrorResponse.Fail(ex.Message);
|
||||
}
|
||||
catch (System.IO.PathTooLongException ex)
|
||||
{
|
||||
return ErrorResponse.Fail(ex.Message);
|
||||
}
|
||||
catch (NotSupportedException ex)
|
||||
{
|
||||
return ErrorResponse.Fail(ex.Message);
|
||||
}
|
||||
return ErrorResponse.Success;
|
||||
}
|
||||
|
||||
public static IErrorResponse IsDirectoryPathValid(string path)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(path))
|
||||
{
|
||||
return ErrorResponse.Fail("Path was empty");
|
||||
}
|
||||
try
|
||||
{
|
||||
var fi = new System.IO.DirectoryInfo(path);
|
||||
}
|
||||
catch (ArgumentException ex)
|
||||
{
|
||||
return ErrorResponse.Fail(ex.Message);
|
||||
}
|
||||
catch (System.IO.PathTooLongException ex)
|
||||
{
|
||||
return ErrorResponse.Fail(ex.Message);
|
||||
}
|
||||
catch (NotSupportedException ex)
|
||||
{
|
||||
return ErrorResponse.Fail(ex.Message);
|
||||
}
|
||||
return ErrorResponse.Success;
|
||||
}
|
||||
}
|
||||
}
|
@ -89,7 +89,10 @@
|
||||
<Compile Include="ChildProcessTracker.cs" />
|
||||
<Compile Include="Consts.cs" />
|
||||
<Compile Include="DynamicIniData.cs" />
|
||||
<Compile Include="Error States\ErrorResponse.cs" />
|
||||
<Compile Include="Error States\GetResponse.cs" />
|
||||
<Compile Include="ExtensionManager.cs" />
|
||||
<Compile Include="Extensions\HashHelper.cs" />
|
||||
<Compile Include="FileExtractor.cs" />
|
||||
<Compile Include="GameMetaData.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
|
@ -64,11 +64,17 @@ namespace Wabbajack
|
||||
public bool InstallingMode { get; set; }
|
||||
|
||||
[Reactive]
|
||||
public string Location { get; set; } = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
|
||||
public string Location { get; set; }
|
||||
|
||||
private readonly ObservableAsPropertyHelper<IErrorResponse> _LocationError;
|
||||
public IErrorResponse LocationError => _LocationError.Value;
|
||||
|
||||
[Reactive]
|
||||
public string DownloadLocation { get; set; }
|
||||
|
||||
private readonly ObservableAsPropertyHelper<IErrorResponse> _DownloadLocationError;
|
||||
public IErrorResponse DownloadLocationError => _DownloadLocationError.Value;
|
||||
|
||||
private readonly ObservableAsPropertyHelper<float> _ProgressPercent;
|
||||
public float ProgressPercent => _ProgressPercent.Value;
|
||||
|
||||
@ -222,6 +228,14 @@ namespace Wabbajack
|
||||
resultSelector: (modList, mod, installing) => installing ? mod : modList)
|
||||
.ToProperty(this, nameof(this.Description));
|
||||
|
||||
this._LocationError = this.WhenAny(x => x.Location)
|
||||
.Select(x => Utils.IsDirectoryPathValid(x))
|
||||
.ToProperty(this, nameof(this.LocationError));
|
||||
|
||||
this._DownloadLocationError = this.WhenAny(x => x.DownloadLocation)
|
||||
.Select(x => Utils.IsDirectoryPathValid(x))
|
||||
.ToProperty(this, nameof(this.DownloadLocationError));
|
||||
|
||||
// Define commands
|
||||
this.ShowReportCommand = ReactiveCommand.Create(ShowReport);
|
||||
this.OpenReadmeCommand = ReactiveCommand.Create(
|
||||
@ -231,8 +245,16 @@ namespace Wabbajack
|
||||
.ObserveOnGuiThread());
|
||||
this.BeginCommand = ReactiveCommand.Create(
|
||||
execute: this.ExecuteBegin,
|
||||
canExecute: this.WhenAny(x => x.Installing)
|
||||
.Select(installing => !installing)
|
||||
canExecute: Observable.CombineLatest(
|
||||
this.WhenAny(x => x.Installing),
|
||||
this.WhenAny(x => x.LocationError),
|
||||
this.WhenAny(x => x.DownloadLocationError),
|
||||
resultSelector: (installing, loc, download) =>
|
||||
{
|
||||
if (installing) return false;
|
||||
return (loc?.Succeeded ?? false)
|
||||
&& (download?.Succeeded ?? false);
|
||||
})
|
||||
.ObserveOnGuiThread());
|
||||
this.VisitWebsiteCommand = ReactiveCommand.Create(
|
||||
execute: () => Process.Start(this.ModList.Website),
|
||||
@ -242,6 +264,7 @@ namespace Wabbajack
|
||||
|
||||
// Have Installation location updates modify the downloads location if empty
|
||||
this.WhenAny(x => x.Location)
|
||||
.Skip(1) // Don't do it initially
|
||||
.Subscribe(installPath =>
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(this.DownloadLocation))
|
||||
|
@ -29,8 +29,8 @@
|
||||
VerticalAlignment="Center"
|
||||
Foreground="{StaticResource WarningBrush}"
|
||||
Kind="Circle"
|
||||
ToolTip="Path does not exist"
|
||||
Visibility="{Binding Exists, RelativeSource={RelativeSource AncestorType={x:Type UserControl}}, Converter={StaticResource bool2VisibilityConverter}, ConverterParameter=False}" />
|
||||
ToolTip="{Binding ErrorTooltip, RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}"
|
||||
Visibility="{Binding InError, RelativeSource={RelativeSource AncestorType={x:Type UserControl}}, Converter={StaticResource bool2VisibilityConverter}}" />
|
||||
<Button
|
||||
Grid.Column="1"
|
||||
Command="{Binding SetTargetPathCommand, RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}"
|
||||
|
@ -97,6 +97,20 @@ namespace Wabbajack
|
||||
public static readonly DependencyProperty FilterProperty = DependencyProperty.Register(nameof(Filter), typeof(string), typeof(FilePicker),
|
||||
new FrameworkPropertyMetadata(default(string)));
|
||||
|
||||
public IErrorResponse AdditionalError
|
||||
{
|
||||
get => (IErrorResponse)GetValue(AdditionalErrorProperty);
|
||||
set => SetValue(AdditionalErrorProperty, value);
|
||||
}
|
||||
public static readonly DependencyProperty AdditionalErrorProperty = DependencyProperty.Register(nameof(AdditionalError), typeof(IErrorResponse), typeof(FilePicker),
|
||||
new FrameworkPropertyMetadata(default(IErrorResponse), WireNotifyPropertyChanged));
|
||||
|
||||
private readonly ObservableAsPropertyHelper<bool> _InError;
|
||||
public bool InError => _InError.Value;
|
||||
|
||||
private readonly ObservableAsPropertyHelper<string> _ErrorTooltip;
|
||||
public string ErrorTooltip => _ErrorTooltip.Value;
|
||||
|
||||
public FilePicker()
|
||||
{
|
||||
InitializeComponent();
|
||||
@ -175,6 +189,28 @@ namespace Wabbajack
|
||||
.ObserveOn(RxApp.MainThreadScheduler)
|
||||
.Subscribe(exists => this.Exists = exists)
|
||||
.DisposeWith(this.CompositeDisposable);
|
||||
|
||||
this._InError = Observable.CombineLatest(
|
||||
this.WhenAny(x => x.Exists),
|
||||
this.WhenAny(x => x.AdditionalError)
|
||||
.Select(err => !err?.Succeeded ?? true),
|
||||
resultSelector: (exist, err) => !exist || err)
|
||||
.ToProperty(this, nameof(this.InError));
|
||||
|
||||
this._ErrorTooltip = Observable.CombineLatest(
|
||||
this.WhenAny(x => x.Exists)
|
||||
.Select(exists => exists ? default(string) : "Path does not exist"),
|
||||
this.WhenAny(x => x.AdditionalError),
|
||||
resultSelector: (exists, err) =>
|
||||
{
|
||||
if ((!err?.Succeeded ?? false)
|
||||
&& !string.IsNullOrWhiteSpace(err.Reason))
|
||||
{
|
||||
return err.Reason;
|
||||
}
|
||||
return exists;
|
||||
})
|
||||
.ToProperty(this, nameof(this.ErrorTooltip));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -617,7 +617,8 @@
|
||||
Margin="0,0,14,0"
|
||||
HorizontalAlignment="Right"
|
||||
Background="{StaticResource PrimaryVariantBrush}"
|
||||
CornerRadius="43">
|
||||
CornerRadius="43"
|
||||
Visibility="{Binding IsEnabled, ElementName=BeginButton, Converter={StaticResource bool2VisibilityConverter}}">
|
||||
<Border.Effect>
|
||||
<BlurEffect Radius="10" />
|
||||
</Border.Effect>
|
||||
@ -645,6 +646,7 @@
|
||||
Grid.Column="2"
|
||||
Height="30"
|
||||
VerticalAlignment="Center"
|
||||
AdditionalError="{Binding LocationError}"
|
||||
DoExistsCheck="False"
|
||||
FontSize="14"
|
||||
PathType="Folder"
|
||||
@ -663,6 +665,7 @@
|
||||
Grid.Column="2"
|
||||
Height="30"
|
||||
VerticalAlignment="Center"
|
||||
AdditionalError="{Binding DownloadLocationError}"
|
||||
DoExistsCheck="False"
|
||||
FontSize="14"
|
||||
PathType="Folder"
|
||||
@ -677,10 +680,7 @@
|
||||
Height="55"
|
||||
Margin="0,0,25,0"
|
||||
HorizontalAlignment="Right"
|
||||
Background="#222222"
|
||||
BorderBrush="{StaticResource SecondaryBrush}"
|
||||
Command="{Binding BeginCommand}"
|
||||
Style="{StaticResource CircleButtonStyle}">
|
||||
Command="{Binding BeginCommand}">
|
||||
<icon:PackIconMaterial
|
||||
Width="25"
|
||||
Height="25"
|
||||
@ -688,21 +688,43 @@
|
||||
Kind="Play">
|
||||
<icon:PackIconMaterial.Style>
|
||||
<Style TargetType="icon:PackIconMaterial">
|
||||
<Setter Property="Foreground" Value="{StaticResource SecondaryBrush}" />
|
||||
<Setter Property="Foreground" Value="#666666" />
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding IsMouseOver, ElementName=BeginButton}" Value="True">
|
||||
<Setter Property="Foreground" Value="#00ffe7" />
|
||||
<DataTrigger Binding="{Binding IsEnabled, ElementName=BeginButton}" Value="True">
|
||||
<Setter Property="Foreground" Value="{StaticResource SecondaryBrush}" />
|
||||
</DataTrigger>
|
||||
<MultiDataTrigger>
|
||||
<MultiDataTrigger.Conditions>
|
||||
<Condition Binding="{Binding IsMouseOver, ElementName=BeginButton}" Value="True" />
|
||||
<Condition Binding="{Binding IsEnabled, ElementName=BeginButton}" Value="True" />
|
||||
</MultiDataTrigger.Conditions>
|
||||
<MultiDataTrigger.Setters>
|
||||
<Setter Property="Foreground" Value="#00ffe7" />
|
||||
</MultiDataTrigger.Setters>
|
||||
</MultiDataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</icon:PackIconMaterial.Style>
|
||||
</icon:PackIconMaterial>
|
||||
<Button.Effect>
|
||||
<DropShadowEffect
|
||||
BlurRadius="15"
|
||||
ShadowDepth="0"
|
||||
Color="{StaticResource Secondary}" />
|
||||
</Button.Effect>
|
||||
<Button.Style>
|
||||
<Style BasedOn="{StaticResource CircleButtonStyle}" TargetType="Button">
|
||||
<Setter Property="Background" Value="#333333" />
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding IsEnabled, ElementName=BeginButton}" Value="True">
|
||||
<Setter Property="BorderBrush" Value="{StaticResource SecondaryBrush}" />
|
||||
<Setter Property="Background" Value="#222222" />
|
||||
<Setter Property="Effect">
|
||||
<Setter.Value>
|
||||
<DropShadowEffect
|
||||
BlurRadius="15"
|
||||
ShadowDepth="0"
|
||||
Color="{StaticResource Secondary}" />
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</Button.Style>
|
||||
</Button>
|
||||
</Grid>
|
||||
</ScrollViewer>
|
||||
|
Loading…
Reference in New Issue
Block a user