mirror of
https://github.com/gwdevhub/Daybreak.git
synced 2026-09-16 13:29:30 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6c2d4a1e70 | ||
|
|
be03f1a32d | ||
|
|
3ed1cc453a | ||
|
|
16030063ed | ||
|
|
458696ad8f | ||
|
|
6201702563 | ||
|
|
c5bea23a8f | ||
|
|
e5f38f77ef | ||
|
|
1d774ab8de | ||
|
|
bc66ca9948 | ||
|
|
524cd21fd4 | ||
|
|
132cb0e1f4 | ||
|
|
09c99e7731 | ||
|
|
c9d0be1117 | ||
|
|
965055c8d7 | ||
|
|
f6bb21d0ef | ||
|
|
465e0a4ce0 | ||
|
|
55f304b885 | ||
|
|
0cb1d97332 | ||
|
|
e2091cd82f | ||
|
|
d2bada4159 | ||
|
|
b27998d7f2 | ||
|
|
98d3e21db9 | ||
|
|
0683504330 | ||
|
|
98bd1b2de6 | ||
|
|
c169ca1684 | ||
|
|
88214ea166 | ||
|
|
4bdcd1a811 | ||
|
|
fa4f665a3e | ||
|
|
e59e022c0a | ||
|
|
d096dc696a | ||
|
|
071007c3e5 | ||
|
|
57192d5043 | ||
|
|
6af72683a8 | ||
|
|
3af9567506 | ||
|
|
1d7adf3944 | ||
|
|
fb7399adf8 | ||
|
|
6ebbffdda1 | ||
|
|
2c35333cac | ||
|
|
fe5e38b216 | ||
|
|
9fd7d8b62a | ||
|
|
a9aa73033f | ||
|
|
73dfca0bc0 | ||
|
|
cdc9b6b011 | ||
|
|
bbdd365a28 | ||
|
|
ec19ce6561 | ||
|
|
9e62860d8d |
@@ -0,0 +1,22 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0-windows</TargetFramework>
|
||||
|
||||
<IsPackable>false</IsPackable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="FluentAssertions" Version="6.0.0-alpha0002" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.7.1" />
|
||||
<PackageReference Include="Moq" Version="4.16.1" />
|
||||
<PackageReference Include="MSTest.TestAdapter" Version="2.1.1" />
|
||||
<PackageReference Include="MSTest.TestFramework" Version="2.1.1" />
|
||||
<PackageReference Include="coverlet.collector" Version="1.3.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Daybreak\Daybreak.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,96 @@
|
||||
using Daybreak.Models.Builds;
|
||||
using Daybreak.Services.BuildTemplates;
|
||||
using Daybreak.Services.Logging;
|
||||
using FluentAssertions;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Moq;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Daybreak.Tests.Services
|
||||
{
|
||||
[TestClass]
|
||||
public class BuildTemplateManagerTests
|
||||
{
|
||||
private const string EncodedTemplate = "OwBk0texXNu0Dj/z+TDzBj+TN4AE";
|
||||
private IBuildTemplateManager buildTemplateManager;
|
||||
|
||||
[TestInitialize]
|
||||
public void Initialize()
|
||||
{
|
||||
buildTemplateManager = new BuildTemplateManager(new Mock<ILogger>().Object);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void TestDecode()
|
||||
{
|
||||
var build = this.buildTemplateManager.DecodeTemplate(EncodedTemplate);
|
||||
build.Primary.Should().Be(Profession.Assassin);
|
||||
build.Secondary.Should().Be(Profession.None);
|
||||
build.Attributes.Count.Should().Be(4);
|
||||
build.Attributes[0].Attribute.Should().Be(Attribute.DaggerMastery);
|
||||
build.Attributes[0].Points.Should().Be(11);
|
||||
build.Attributes[1].Attribute.Should().Be(Attribute.DeadlyArts);
|
||||
build.Attributes[1].Points.Should().Be(1);
|
||||
build.Attributes[2].Attribute.Should().Be(Attribute.ShadowArts);
|
||||
build.Attributes[2].Points.Should().Be(5);
|
||||
build.Attributes[3].Attribute.Should().Be(Attribute.CriticalStrikes);
|
||||
build.Attributes[3].Points.Should().Be(11);
|
||||
build.Skills.Count.Should().Be(8);
|
||||
build.Skills[0].Should().Be(Skill.UnsuspectingStrike);
|
||||
build.Skills[1].Should().Be(Skill.WildStrike);
|
||||
build.Skills[2].Should().Be(Skill.CriticalStrike);
|
||||
build.Skills[3].Should().Be(Skill.MoebiusStrike);
|
||||
build.Skills[4].Should().Be(Skill.DeathBlossom);
|
||||
build.Skills[5].Should().Be(Skill.CriticalEye);
|
||||
build.Skills[6].Should().Be(Skill.CriticalAgility);
|
||||
build.Skills[7].Should().Be(Skill.CriticalDefenses);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void TestEncode()
|
||||
{
|
||||
var build = new Build()
|
||||
{
|
||||
Primary = Profession.Assassin,
|
||||
Secondary = Profession.None,
|
||||
Attributes = new List<AttributeEntry>
|
||||
{
|
||||
new AttributeEntry
|
||||
{
|
||||
Attribute = Attribute.DaggerMastery,
|
||||
Points = 11
|
||||
},
|
||||
new AttributeEntry
|
||||
{
|
||||
Attribute = Attribute.DeadlyArts,
|
||||
Points = 1
|
||||
},
|
||||
new AttributeEntry
|
||||
{
|
||||
Attribute = Attribute.ShadowArts,
|
||||
Points = 5
|
||||
},
|
||||
new AttributeEntry
|
||||
{
|
||||
Attribute = Attribute.CriticalStrikes,
|
||||
Points = 11
|
||||
}
|
||||
},
|
||||
Skills = new List<Skill>
|
||||
{
|
||||
Skill.UnsuspectingStrike,
|
||||
Skill.WildStrike,
|
||||
Skill.CriticalStrike,
|
||||
Skill.MoebiusStrike,
|
||||
Skill.DeathBlossom,
|
||||
Skill.CriticalEye,
|
||||
Skill.CriticalAgility,
|
||||
Skill.CriticalDefenses
|
||||
}
|
||||
};
|
||||
|
||||
var encoded = this.buildTemplateManager.EncodeTemplate(build);
|
||||
encoded.Should().Be(EncodedTemplate);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,8 @@ VisualStudioVersion = 16.0.31005.135
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Daybreak", "Daybreak\Daybreak.csproj", "{AA45C2B1-8BD0-466C-9271-699F168905AF}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Daybreak.Tests", "Daybreak.Tests\Daybreak.Tests.csproj", "{C911C1C2-6566-419C-89C7-F802EB3FE709}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
@@ -21,6 +23,14 @@ Global
|
||||
{AA45C2B1-8BD0-466C-9271-699F168905AF}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{AA45C2B1-8BD0-466C-9271-699F168905AF}.Release|x64.ActiveCfg = Release|x64
|
||||
{AA45C2B1-8BD0-466C-9271-699F168905AF}.Release|x64.Build.0 = Release|x64
|
||||
{C911C1C2-6566-419C-89C7-F802EB3FE709}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{C911C1C2-6566-419C-89C7-F802EB3FE709}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{C911C1C2-6566-419C-89C7-F802EB3FE709}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{C911C1C2-6566-419C-89C7-F802EB3FE709}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{C911C1C2-6566-419C-89C7-F802EB3FE709}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{C911C1C2-6566-419C-89C7-F802EB3FE709}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{C911C1C2-6566-419C-89C7-F802EB3FE709}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{C911C1C2-6566-419C-89C7-F802EB3FE709}.Release|x64.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Globalization;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Interactivity;
|
||||
using System.Windows.Media;
|
||||
|
||||
namespace Daybreak.Behaviors
|
||||
{
|
||||
public class ScaleFontWithSize : Behavior<TextBlock>
|
||||
{
|
||||
public static readonly DependencyProperty MaxFontSizeProperty = DependencyProperty.Register("MaxFontSize", typeof(double), typeof(ScaleFontWithSize), new PropertyMetadata(12d));
|
||||
|
||||
public double MaxFontSize
|
||||
{
|
||||
get
|
||||
{
|
||||
return (double)this.GetValue(MaxFontSizeProperty);
|
||||
}
|
||||
set
|
||||
{
|
||||
this.SetValue(MaxFontSizeProperty, value);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnAttached()
|
||||
{
|
||||
base.OnAttached();
|
||||
this.AssociatedObject.SizeChanged += (_, __) => this.CalculateFontSize();
|
||||
DependencyPropertyDescriptor.FromProperty(
|
||||
TextBlock.TextProperty, typeof(TextBlock)).AddValueChanged(this.AssociatedObject, (_, __) => this.CalculateFontSize());
|
||||
DependencyPropertyDescriptor.FromProperty(
|
||||
TextBlock.FontSizeProperty, typeof(TextBlock)).AddValueChanged(this.AssociatedObject, (_, __) => this.CalculateFontSize());
|
||||
}
|
||||
|
||||
private void CalculateFontSize()
|
||||
{
|
||||
var textMeasurement = this.MeasureText(this.AssociatedObject.FontSize);
|
||||
var maximumTextMeasurement = this.MeasureText(this.MaxFontSize);
|
||||
var desiredWidthFontSize = this.MaxFontSize;
|
||||
var desiredHeightFontSize = this.MaxFontSize;
|
||||
|
||||
if (Math.Round(textMeasurement.Height) != Math.Round(this.AssociatedObject.ActualHeight))
|
||||
{
|
||||
|
||||
var scale = this.AssociatedObject.ActualHeight / maximumTextMeasurement.Height;
|
||||
desiredHeightFontSize = (this.MaxFontSize * scale) - 1;
|
||||
desiredHeightFontSize = desiredHeightFontSize <= this.MaxFontSize ? desiredHeightFontSize : this.MaxFontSize;
|
||||
}
|
||||
|
||||
if (Math.Round(textMeasurement.Width) != Math.Round(this.AssociatedObject.ActualWidth))
|
||||
{
|
||||
var scale = this.AssociatedObject.ActualWidth / maximumTextMeasurement.Width;
|
||||
desiredWidthFontSize = (this.MaxFontSize * scale) - 1;
|
||||
desiredWidthFontSize = desiredWidthFontSize <= this.MaxFontSize ? desiredWidthFontSize : this.MaxFontSize;
|
||||
|
||||
}
|
||||
|
||||
var desiredFontSize = Math.Min(desiredHeightFontSize, desiredWidthFontSize);
|
||||
|
||||
if ((int)desiredFontSize != (int)this.AssociatedObject.FontSize && desiredFontSize > 0)
|
||||
{
|
||||
this.AssociatedObject.FontSize = desiredFontSize;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
private Size MeasureText(double fontSize)
|
||||
{
|
||||
var formattedText = new FormattedText(this.AssociatedObject.Text, CultureInfo.CurrentUICulture,
|
||||
FlowDirection.LeftToRight,
|
||||
new Typeface(this.AssociatedObject.FontFamily, this.AssociatedObject.FontStyle, this.AssociatedObject.FontWeight, this.AssociatedObject.FontStretch),
|
||||
fontSize, Brushes.Black, VisualTreeHelper.GetDpi(this.AssociatedObject).PixelsPerDip);
|
||||
|
||||
return new Size(formattedText.Width, formattedText.Height);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
using System;
|
||||
using System.Extensions;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Interactivity;
|
||||
|
||||
namespace Daybreak.Behaviors
|
||||
{
|
||||
public class ScrollIntoView : Behavior<ListView>
|
||||
{
|
||||
/// <summary>
|
||||
/// When Beahvior is attached
|
||||
/// </summary>
|
||||
protected override void OnAttached()
|
||||
{
|
||||
base.OnAttached();
|
||||
this.AssociatedObject.SelectionChanged += AssociatedObject_SelectionChanged;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// On Selection Changed
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="e"></param>
|
||||
void AssociatedObject_SelectionChanged(object sender,
|
||||
SelectionChangedEventArgs e)
|
||||
{
|
||||
if (sender is ListView)
|
||||
{
|
||||
var listView = sender.As<ListView>();
|
||||
if (listView.SelectedItem != null)
|
||||
{
|
||||
listView.Dispatcher.BeginInvoke(
|
||||
(Action)(() =>
|
||||
{
|
||||
listView.UpdateLayout();
|
||||
if (listView.SelectedItem !=
|
||||
null)
|
||||
listView.ScrollIntoView(
|
||||
listView.SelectedItem);
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// When behavior is detached
|
||||
/// </summary>
|
||||
protected override void OnDetaching()
|
||||
{
|
||||
base.OnDetaching();
|
||||
this.AssociatedObject.SelectionChanged -=
|
||||
AssociatedObject_SelectionChanged;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,24 +1,30 @@
|
||||
using Newtonsoft.Json;
|
||||
using Daybreak.Models;
|
||||
using Newtonsoft.Json;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Daybreak.Configuration
|
||||
{
|
||||
public sealed class ApplicationConfiguration
|
||||
{
|
||||
[JsonProperty("GamePath")]
|
||||
public string GamePath { get; set; }
|
||||
[JsonProperty("BrowsersEnabled")]
|
||||
public bool BrowsersEnabled { get; set; } = true;
|
||||
[JsonProperty("ToolboxPath")]
|
||||
public string ToolboxPath { get; set; }
|
||||
[JsonProperty("CharacterName")]
|
||||
public string CharacterName { get; set; }
|
||||
[JsonProperty("TexmodPath")]
|
||||
public string TexmodPath { get; set; }
|
||||
[JsonProperty("ToolboxAutoLaunch")]
|
||||
public bool ToolboxAutoLaunch { get; set; }
|
||||
[JsonProperty("LeftBrowserDefault")]
|
||||
public string LeftBrowserDefault { get; set; }
|
||||
public string LeftBrowserDefault { get; set; } = "https://gwpvx.fandom.com/wiki/PvX_wiki";
|
||||
[JsonProperty("RightBrowserDefault")]
|
||||
public string RightBrowserDefault { get; set; }
|
||||
[JsonProperty("ProtectedUsername")]
|
||||
public string ProtectedUsername { get; set; }
|
||||
[JsonProperty("ProtectedPassword")]
|
||||
public string ProtectedPassword { get; set; }
|
||||
public string RightBrowserDefault { get; set; } = "https://wiki.guildwars.com/wiki/Quick_access_links";
|
||||
[JsonProperty("GuildwarsPaths")]
|
||||
public List<GuildwarsPath> GuildwarsPaths { get; set; } = new();
|
||||
[JsonProperty("ProtectedLoginCredentials")]
|
||||
public List<ProtectedLoginCredentials> ProtectedLoginCredentials { get; set; } = new();
|
||||
[JsonProperty("AddressBarReadonly")]
|
||||
public bool AddressBarReadonly { get; set; } = true;
|
||||
[JsonProperty("ExperimentalFeatures")]
|
||||
public ExperimentalFeatures ExperimentalFeatures { get; set; } = new();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Daybreak.Configuration
|
||||
{
|
||||
public sealed class ExperimentalFeatures
|
||||
{
|
||||
[JsonProperty("MultiLaunchSupport")]
|
||||
public bool MultiLaunchSupport { get; set; }
|
||||
[JsonProperty("ToolboxAutoLaunchDelay")]
|
||||
public int ToolboxAutoLaunchDelay { get; set; } = 5000;
|
||||
[JsonProperty("DynamicBuildLoading")]
|
||||
public bool DynamicBuildLoading { get; set; } = true;
|
||||
[JsonProperty("LaunchGuildwarsAsCurrentUser")]
|
||||
public bool LaunchGuildwarsAsCurrentUser { get; set; } = true;
|
||||
}
|
||||
}
|
||||
@@ -1,19 +1,23 @@
|
||||
using Daybreak.Services.ApplicationDetection;
|
||||
using Daybreak.Services.ApplicationLauncher;
|
||||
using Daybreak.Services.ApplicationLifetime;
|
||||
using Daybreak.Services.Bloogum;
|
||||
using Daybreak.Services.BuildTemplates;
|
||||
using Daybreak.Services.Configuration;
|
||||
using Daybreak.Services.Credentials;
|
||||
using Daybreak.Services.IconRetrieve;
|
||||
using Daybreak.Services.Logging;
|
||||
using Daybreak.Services.Mutex;
|
||||
using Daybreak.Services.Privilege;
|
||||
using Daybreak.Services.Runtime;
|
||||
using Daybreak.Services.Screenshots;
|
||||
using Daybreak.Services.Updater;
|
||||
using Daybreak.Services.ViewManagement;
|
||||
using Daybreak.Views;
|
||||
using Microsoft.Web.WebView2.Core;
|
||||
using Slim;
|
||||
using System.Extensions;
|
||||
|
||||
namespace Daybreak.Configuration
|
||||
{
|
||||
// TODO: Credit http://bloogum.net/guildwars/
|
||||
public static class ProjectConfiguration
|
||||
{
|
||||
public static void RegisterServices(IServiceProducer serviceProducer)
|
||||
@@ -25,11 +29,16 @@ namespace Daybreak.Configuration
|
||||
serviceProducer.RegisterSingleton<ILogger, Logger>();
|
||||
serviceProducer.RegisterSingleton<ApplicationLifetimeManager>();
|
||||
serviceProducer.RegisterSingleton<ViewManager>();
|
||||
serviceProducer.RegisterSingleton<IApplicationDetector, ApplicationDetector>();
|
||||
serviceProducer.RegisterSingleton<IApplicationLauncher, ApplicationLauncher>();
|
||||
serviceProducer.RegisterSingleton<IScreenshotProvider, ScreenshotProvider>();
|
||||
serviceProducer.RegisterSingleton<IConfigurationManager, ConfigurationManager>();
|
||||
serviceProducer.RegisterSingleton<IBloogumClient, BloogumClient>();
|
||||
serviceProducer.RegisterSingleton<CoreWebView2Environment, CoreWebView2Environment>((sp) => TaskExtensions.RunSync(() => CoreWebView2Environment.CreateAsync(null, "BrowserData", null)));
|
||||
serviceProducer.RegisterSingleton<IApplicationUpdater, ApplicationUpdater>();
|
||||
serviceProducer.RegisterSingleton<IMutexHandler, MutexHandler>();
|
||||
serviceProducer.RegisterSingleton<IRuntimeStore, RuntimeStore>();
|
||||
serviceProducer.RegisterSingleton<IBuildTemplateManager, BuildTemplateManager>();
|
||||
serviceProducer.RegisterSingleton<IIconRetriever, IconRetriever>();
|
||||
serviceProducer.RegisterSingleton<IPrivilegeManager, PrivilegeManager>();
|
||||
}
|
||||
public static void RegisterLifetimeServices(IApplicationLifetimeProducer applicationLifetimeProducer)
|
||||
{
|
||||
@@ -37,6 +46,7 @@ namespace Daybreak.Configuration
|
||||
|
||||
applicationLifetimeProducer.RegisterService<ILoggingDatabase>();
|
||||
applicationLifetimeProducer.RegisterService<IScreenshotProvider>();
|
||||
applicationLifetimeProducer.RegisterService<IApplicationUpdater>();
|
||||
}
|
||||
public static void RegisterViews(IViewProducer viewProducer)
|
||||
{
|
||||
@@ -44,6 +54,15 @@ namespace Daybreak.Configuration
|
||||
|
||||
viewProducer.RegisterView<MainView>();
|
||||
viewProducer.RegisterView<SettingsView>();
|
||||
viewProducer.RegisterView<AskUpdateView>();
|
||||
viewProducer.RegisterView<UpdateView>();
|
||||
viewProducer.RegisterView<SettingsCategoryView>();
|
||||
viewProducer.RegisterView<AccountsView>();
|
||||
viewProducer.RegisterView<ExperimentalSettingsView>();
|
||||
viewProducer.RegisterView<ExecutablesView>();
|
||||
viewProducer.RegisterView<BuildTemplateView>();
|
||||
viewProducer.RegisterView<BuildsListView>();
|
||||
viewProducer.RegisterView<RequestElevationView>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
<UserControl x:Class="Daybreak.Controls.AddButton"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:Daybreak.Controls"
|
||||
mc:Ignorable="d"
|
||||
x:Name="_this"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<Viewbox>
|
||||
<Grid>
|
||||
<Ellipse x:Name="BackgroundEllipse" Fill="{Binding ElementName=_this, Path=Foreground, Mode=OneWay}" Visibility="Visible" Opacity="0.1" />
|
||||
<Path Data="m13,26a13,13 0 1 1 13,-13a13,13 0 0 1 -13,13zm0,-24a11,11 0 1 0 11,11a11,11 0 0 0 -11,-11z"
|
||||
Fill="{Binding ElementName=_this, Path=Foreground, Mode=OneWay}"></Path>
|
||||
<Path Data="m13,20a1,1 0 0 1 -1,-1l0,-12a1,1 0 0 1 2,0l0,12a1,1 0 0 1 -1,1z"
|
||||
Fill="{Binding ElementName=_this, Path=Foreground, Mode=OneWay}"></Path>
|
||||
<Path Data="m19,14l-12,0a1,1 0 0 1 0,-2l12,0a1,1 0 0 1 0,2z"
|
||||
Fill="{Binding ElementName=_this, Path=Foreground, Mode=OneWay}"></Path>
|
||||
<Ellipse Fill="Transparent" MouseEnter="Ellipse_MouseEnter" MouseLeave="Ellipse_MouseLeave" MouseLeftButtonDown="Ellipse_MouseLeftButtonDown"></Ellipse>
|
||||
</Grid>
|
||||
</Viewbox>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,37 @@
|
||||
using System;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace Daybreak.Controls
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for AddButton.xaml
|
||||
/// </summary>
|
||||
public partial class AddButton : UserControl
|
||||
{
|
||||
public event EventHandler Clicked;
|
||||
|
||||
public AddButton()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void Ellipse_MouseEnter(object sender, MouseEventArgs e)
|
||||
{
|
||||
this.BackgroundEllipse.Opacity = 0.6;
|
||||
}
|
||||
|
||||
private void Ellipse_MouseLeave(object sender, MouseEventArgs e)
|
||||
{
|
||||
this.BackgroundEllipse.Opacity = 0;
|
||||
}
|
||||
|
||||
private void Ellipse_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
if (e.ChangedButton == MouseButton.Left)
|
||||
{
|
||||
Clicked?.Invoke(this, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
<UserControl x:Class="Daybreak.Controls.BinButton"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:Daybreak.Controls"
|
||||
mc:Ignorable="d"
|
||||
x:Name="_this"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<Viewbox>
|
||||
<Grid>
|
||||
<Ellipse x:Name="BackgroundEllipse" Fill="{Binding ElementName=_this, Path=Foreground, Mode=OneWay}" Width="80" Height="80" Opacity="0.6"
|
||||
Visibility="Hidden"></Ellipse>
|
||||
<Path Data="m40,7l-2,0l0,-5l-18,0l0,5l-2,0l0,-6a1,1 0 0 1 1,-1l20,0a1,1 0 0 1 1,1l0,6z"
|
||||
Fill="{Binding ElementName=_this, Path=Foreground, Mode=OneWay}" Margin="11"></Path>
|
||||
<Path Data="m58,14l-2,0l0,-3l-54,0l0,3l-2,0l0,-4a1,1 0 0 1 1,-1l56,0a1,1 0 0 1 1,1l0,4z"
|
||||
Fill="{Binding ElementName=_this, Path=Foreground, Mode=OneWay}" Margin="11"></Path>
|
||||
<Path Data="m51,64l-44,0a1,1 0 0 1 -1,-1l0,-48l2,0l0,47l42,0l0,-47l2,0l0,48a1,1 0 0 1 -1,1z"
|
||||
Fill="{Binding ElementName=_this, Path=Foreground, Mode=OneWay}" Margin="11"></Path>
|
||||
<Rectangle Margin="38, 32, 0, 0" Width="2" Height="32" Stroke="{Binding ElementName=_this, Path=Foreground, Mode=OneWay}"
|
||||
VerticalAlignment="Top" HorizontalAlignment="Left"></Rectangle>
|
||||
<Rectangle Margin="26, 35, 0, 0" Width="2" Height="32" Stroke="{Binding ElementName=_this, Path=Foreground, Mode=OneWay}"
|
||||
VerticalAlignment="Top" HorizontalAlignment="Left"></Rectangle>
|
||||
<Rectangle Margin="50, 35, 0, 0" Width="2" Height="32" Stroke="{Binding ElementName=_this, Path=Foreground, Mode=OneWay}"
|
||||
VerticalAlignment="Top" HorizontalAlignment="Left"></Rectangle>
|
||||
<Ellipse Stroke="{Binding ElementName=_this, Path=Foreground, Mode=OneWay}" StrokeThickness="3" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Fill="Transparent"
|
||||
MouseLeftButtonDown="Ellipse_MouseLeftButtonDown" MouseEnter="Ellipse_MouseEnter" MouseLeave="Ellipse_MouseLeave"></Ellipse>
|
||||
</Grid>
|
||||
</Viewbox>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,36 @@
|
||||
using System;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace Daybreak.Controls
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for BinButton.xaml
|
||||
/// </summary>
|
||||
public partial class BinButton : UserControl
|
||||
{
|
||||
public event EventHandler Clicked;
|
||||
public BinButton()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void Ellipse_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
if (e.ChangedButton == MouseButton.Left)
|
||||
{
|
||||
this.Clicked?.Invoke(this, e);
|
||||
}
|
||||
}
|
||||
|
||||
private void Ellipse_MouseEnter(object sender, MouseEventArgs e)
|
||||
{
|
||||
this.BackgroundEllipse.Visibility = System.Windows.Visibility.Visible;
|
||||
}
|
||||
|
||||
private void Ellipse_MouseLeave(object sender, MouseEventArgs e)
|
||||
{
|
||||
this.BackgroundEllipse.Visibility = System.Windows.Visibility.Hidden;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
<UserControl x:Class="Daybreak.Controls.FilePickerGlyph"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:Daybreak.Controls"
|
||||
mc:Ignorable="d"
|
||||
x:Name="_this"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<Grid>
|
||||
<Ellipse x:Name="BackgroundEllipse" Fill="{Binding ElementName=_this, Path=Foreground, Mode=OneWay}" Visibility="Visible" Opacity="0.1" />
|
||||
<Viewbox Stretch="Fill">
|
||||
<Grid>
|
||||
<Ellipse Height="4" Width="4" StrokeThickness="0.2" Stroke="{Binding ElementName=_this, Path=Foreground, Mode=OneWay}"></Ellipse>
|
||||
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
|
||||
<Ellipse Fill="{Binding ElementName=_this, Path=Foreground, Mode=OneWay}" Height="1" Width="1"></Ellipse>
|
||||
<Ellipse Fill="{Binding ElementName=_this, Path=Foreground, Mode=OneWay}" Height="1" Width="1"></Ellipse>
|
||||
<Ellipse Fill="{Binding ElementName=_this, Path=Foreground, Mode=OneWay}" Height="1" Width="1"></Ellipse>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Viewbox>
|
||||
<Ellipse Fill="Transparent" MouseEnter="Ellipse_MouseEnter" MouseLeave="Ellipse_MouseLeave" MouseLeftButtonDown="Ellipse_MouseLeftButtonDown"></Ellipse>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,19 @@
|
||||
<UserControl x:Class="Daybreak.Controls.HelpButton"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:Daybreak.Controls"
|
||||
mc:Ignorable="d"
|
||||
x:Name="_this"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<Viewbox>
|
||||
<Grid>
|
||||
<Ellipse x:Name="BackgroundEllipse" Fill="{Binding ElementName=_this, Path=Foreground, Mode=OneWay}" Visibility="Visible" Opacity="0.1" Width="30" Height="30" />
|
||||
<Ellipse Width="30" Height="30" StrokeThickness="2" Stroke="{Binding ElementName=_this, Path=Foreground, Mode=OneWay}"></Ellipse>
|
||||
<Path Fill="{Binding ElementName=_this, Path=Foreground, Mode=OneWay}" VerticalAlignment="Center" HorizontalAlignment="Center"
|
||||
Data="m4.99353,17.899l0,-1.47c0,-1.436 0.322,-2.188 1.075,-3.229l2.404,-3.3c1.254,-1.721 1.684,-2.546 1.684,-3.766c0,-2.044 -1.434,-3.335 -3.479,-3.335c-2.008,0 -3.299,1.219 -3.729,3.407c-0.036,0.215 -0.179,0.323 -0.395,0.287l-2.259,-0.395c-0.216,-0.036 -0.323,-0.179 -0.288,-0.395c0.539,-3.443 3.014,-5.703 6.744,-5.703c3.872,0 6.49,2.546 6.49,6.097c0,1.722 -0.608,2.977 -1.828,4.663l-2.403,3.3c-0.717,0.968 -0.933,1.47 -0.933,2.689l0,1.147c0,0.215 -0.143,0.358 -0.358,0.358l-2.367,0c-0.215,0.004 -0.358,-0.14 -0.358,-0.355zm-0.179,3.444c0,-0.215 0.143,-0.358 0.359,-0.358l2.726,0c0.215,0 0.358,0.144 0.358,0.358l0,3.084c0,0.216 -0.144,0.358 -0.358,0.358l-2.726,0c-0.217,0 -0.359,-0.143 -0.359,-0.358l0,-3.084z"></Path>
|
||||
<Ellipse Fill="Transparent" MouseEnter="Ellipse_MouseEnter" MouseLeave="Ellipse_MouseLeave" MouseLeftButtonDown="Ellipse_MouseLeftButtonDown"></Ellipse>
|
||||
</Grid>
|
||||
</Viewbox>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,37 @@
|
||||
using System;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace Daybreak.Controls
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for AddButton.xaml
|
||||
/// </summary>
|
||||
public partial class HelpButton : UserControl
|
||||
{
|
||||
public event EventHandler Clicked;
|
||||
|
||||
public HelpButton()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void Ellipse_MouseEnter(object sender, MouseEventArgs e)
|
||||
{
|
||||
this.BackgroundEllipse.Opacity = 0.6;
|
||||
}
|
||||
|
||||
private void Ellipse_MouseLeave(object sender, MouseEventArgs e)
|
||||
{
|
||||
this.BackgroundEllipse.Opacity = 0;
|
||||
}
|
||||
|
||||
private void Ellipse_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
if (e.ChangedButton == MouseButton.Left)
|
||||
{
|
||||
this.Clicked?.Invoke(this, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
<UserControl x:Class="Daybreak.Controls.HomeButton"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:Daybreak.Controls"
|
||||
mc:Ignorable="d"
|
||||
x:Name="_this"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<Viewbox>
|
||||
<Grid>
|
||||
<Ellipse x:Name="BackgroundEllipse" Fill="{Binding ElementName=_this, Path=Foreground, Mode=OneWay}" Visibility="Visible" Opacity="0.1" />
|
||||
<Ellipse Stroke="{Binding ElementName=_this, Path=Foreground, Mode=OneWay}" StrokeThickness="3" Width="60" Height="60"></Ellipse>
|
||||
<Grid VerticalAlignment="Center" HorizontalAlignment="Center">
|
||||
<Path Data="m42,45.384l-14,0l0,-13l-8,0l0,13l-14,0l0,-21c0,-0.552 0.447,-1 1,-1s1,0.448 1,1l0,19l10,0l0,-13l12,0l0,13l10,0l0,-18c0,-0.552 0.447,-1 1,-1s1,0.448 1,1l0,20z"
|
||||
Fill="{Binding ElementName=_this, Path=Foreground, Mode=OneWay}"></Path>
|
||||
<Path Data="m47,24.384c-0.249,0 -0.497,-0.092 -0.691,-0.277l-22.309,-21.339l-22.309,21.339c-0.399,0.381 -1.032,0.368 -1.414,-0.031c-0.382,-0.399 -0.367,-1.032 0.031,-1.414l23.692,-22.662l23.691,22.661c0.398,0.382 0.413,1.015 0.031,1.414c-0.196,0.205 -0.458,0.309 -0.722,0.309z"
|
||||
Fill="{Binding ElementName=_this, Path=Foreground, Mode=OneWay}"></Path>
|
||||
<Path Data="m39,12.384c-0.553,0 -1,-0.448 -1,-1l0,-6l-6,0c-0.553,0 -1,-0.448 -1,-1s0.447,-1 1,-1l8,0l0,8c0,0.552 -0.447,1 -1,1z"
|
||||
Fill="{Binding ElementName=_this, Path=Foreground, Mode=OneWay}"></Path>
|
||||
</Grid>
|
||||
<Ellipse Fill="Transparent" MouseEnter="Ellipse_MouseEnter" MouseLeave="Ellipse_MouseLeave" MouseLeftButtonDown="Ellipse_MouseLeftButtonDown"></Ellipse>
|
||||
</Grid>
|
||||
</Viewbox>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,37 @@
|
||||
using System;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace Daybreak.Controls
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for HomeButton.xaml
|
||||
/// </summary>
|
||||
public partial class HomeButton : UserControl
|
||||
{
|
||||
public event EventHandler Clicked;
|
||||
|
||||
public HomeButton()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
}
|
||||
|
||||
private void Ellipse_MouseEnter(object sender, MouseEventArgs e)
|
||||
{
|
||||
this.BackgroundEllipse.Opacity = 0.6;
|
||||
}
|
||||
|
||||
private void Ellipse_MouseLeave(object sender, MouseEventArgs e)
|
||||
{
|
||||
this.BackgroundEllipse.Opacity = 0;
|
||||
}
|
||||
|
||||
private void Ellipse_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
if (e.ChangedButton == MouseButton.Left)
|
||||
{
|
||||
Clicked?.Invoke(this, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
<UserControl x:Class="Daybreak.Controls.MinusButton"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:Daybreak.Controls"
|
||||
mc:Ignorable="d"
|
||||
x:Name="_this"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<Viewbox>
|
||||
<Grid>
|
||||
<Ellipse x:Name="BackgroundEllipse" Fill="{Binding ElementName=_this, Path=Foreground, Mode=OneWay}" Visibility="Visible" Opacity="0.1" />
|
||||
<Path Data="m13,26a13,13 0 1 1 13,-13a13,13 0 0 1 -13,13zm0,-24a11,11 0 1 0 11,11a11,11 0 0 0 -11,-11z"
|
||||
Fill="{Binding ElementName=_this, Path=Foreground, Mode=OneWay}"></Path>
|
||||
<Path Data="m19,14l-12,0a1,1 0 0 1 0,-2l12,0a1,1 0 0 1 0,2z"
|
||||
Fill="{Binding ElementName=_this, Path=Foreground, Mode=OneWay}"></Path>
|
||||
<Ellipse Fill="Transparent" MouseEnter="Ellipse_MouseEnter" MouseLeave="Ellipse_MouseLeave" MouseLeftButtonDown="Ellipse_MouseLeftButtonDown"></Ellipse>
|
||||
</Grid>
|
||||
</Viewbox>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,37 @@
|
||||
using System;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace Daybreak.Controls
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for AddButton.xaml
|
||||
/// </summary>
|
||||
public partial class MinusButton : UserControl
|
||||
{
|
||||
public event EventHandler Clicked;
|
||||
|
||||
public MinusButton()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void Ellipse_MouseEnter(object sender, MouseEventArgs e)
|
||||
{
|
||||
this.BackgroundEllipse.Opacity = 0.6;
|
||||
}
|
||||
|
||||
private void Ellipse_MouseLeave(object sender, MouseEventArgs e)
|
||||
{
|
||||
this.BackgroundEllipse.Opacity = 0;
|
||||
}
|
||||
|
||||
private void Ellipse_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
if (e.ChangedButton == MouseButton.Left)
|
||||
{
|
||||
Clicked?.Invoke(this, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -21,7 +21,7 @@
|
||||
VerticalAlignment="Top" HorizontalAlignment="Left" StrokeThickness="3" Width="47.25" Height="3" />
|
||||
<Rectangle Stroke="{Binding ElementName=_this, Path=Foreground}" Margin="39.375, 85.625, 0, 0"
|
||||
VerticalAlignment="Top" HorizontalAlignment="Left" StrokeThickness="3" Width="47.25" Height="3" />
|
||||
<Ellipse Stroke="{Binding ElementName=_this, Path=Foreground}" Width="128" Height="128" StrokeThickness="5" Fill="Transparent"
|
||||
<Ellipse Stroke="{Binding ElementName=_this, Path=Foreground}" Width="128" Height="128" StrokeThickness="8" Fill="Transparent"
|
||||
MouseEnter="Ellipse_MouseEnter" MouseLeave="Ellipse_MouseLeave" MouseLeftButtonDown="Ellipse_MouseLeftButtonDown"></Ellipse>
|
||||
</Grid>
|
||||
</Viewbox>
|
||||
@@ -0,0 +1,45 @@
|
||||
<UserControl x:Class="Daybreak.Controls.TileButton"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:Daybreak.Controls"
|
||||
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
|
||||
xmlns:behaviors="clr-namespace:Daybreak.Behaviors"
|
||||
xmlns:converters="clr-namespace:Daybreak.Converters"
|
||||
x:Name="_this"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<UserControl.Resources>
|
||||
<converters:TileButtonHighlightConverter x:Key="HighlightConverter"></converters:TileButtonHighlightConverter>
|
||||
</UserControl.Resources>
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="*"></RowDefinition>
|
||||
<RowDefinition Height="auto"></RowDefinition>
|
||||
</Grid.RowDefinitions>
|
||||
<ContentPresenter x:Name="Content" Margin="5"
|
||||
Content="{Binding ElementName=_this, Path=InnerContent}"></ContentPresenter>
|
||||
<Border BorderBrush="{Binding ElementName=_this, Path=BorderBrush}"
|
||||
BorderThickness="{Binding ElementName=_this, Path=BorderThickness}"
|
||||
Opacity="{Binding ElementName=_this, Path=Highlighted, Converter={StaticResource HighlightConverter}}"
|
||||
Grid.RowSpan="2">
|
||||
</Border>
|
||||
<TextBlock Grid.Row="1" Text="{Binding ElementName=_this, Path=Title}"
|
||||
FontSize="{Binding ElementName=_this, Path=FontSize}"
|
||||
FontFamily="{Binding ElementName=_this, Path=FontFamily}"
|
||||
Foreground="{Binding ElementName=_this, Path=Foreground}"
|
||||
VerticalAlignment="Center" HorizontalAlignment="Stretch" TextWrapping="Wrap"
|
||||
TextAlignment="Center">
|
||||
<i:Interaction.Behaviors>
|
||||
<behaviors:ScaleFontWithSize MaxFontSize="22"></behaviors:ScaleFontWithSize>
|
||||
</i:Interaction.Behaviors>
|
||||
</TextBlock>
|
||||
<Rectangle Fill="Transparent"
|
||||
MouseEnter="Grid_MouseEnter"
|
||||
MouseLeave="Grid_MouseLeave"
|
||||
MouseLeftButtonDown="Rectangle_MouseLeftButtonDown"
|
||||
Grid.RowSpan="2">
|
||||
</Rectangle>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,68 @@
|
||||
using System;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Media;
|
||||
|
||||
namespace Daybreak.Controls
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for TileButton.xaml
|
||||
/// </summary>
|
||||
public partial class TileButton : UserControl
|
||||
{
|
||||
public event EventHandler Clicked;
|
||||
|
||||
public static readonly DependencyProperty HighlightedProperty =
|
||||
DependencyProperty.Register("Highlighted", typeof(bool), typeof(TileButton), null);
|
||||
public static readonly DependencyProperty HighlightColorProperty =
|
||||
DependencyProperty.Register("HighlightColor", typeof(Brush), typeof(TileButton), null);
|
||||
public static readonly DependencyProperty InnerContentProperty =
|
||||
DependencyProperty.Register("InnerContent", typeof(FrameworkElement), typeof(TileButton), null);
|
||||
public static readonly DependencyProperty TitleProperty =
|
||||
DependencyProperty.Register("Title", typeof(string), typeof(TileButton), null);
|
||||
|
||||
public TileButton()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
}
|
||||
|
||||
public bool Highlighted
|
||||
{
|
||||
get => (bool)this.GetValue(HighlightedProperty);
|
||||
set => this.SetValue(HighlightedProperty, value);
|
||||
}
|
||||
|
||||
public string Title
|
||||
{
|
||||
get => this.GetValue(TitleProperty) as string;
|
||||
set => this.SetValue(TitleProperty, value);
|
||||
}
|
||||
|
||||
public FrameworkElement InnerContent
|
||||
{
|
||||
get => this.GetValue(InnerContentProperty) as FrameworkElement;
|
||||
set => this.SetValue(InnerContentProperty, value);
|
||||
}
|
||||
|
||||
public Brush HighlightColor
|
||||
{
|
||||
get => this.GetValue(HighlightColorProperty) as Brush;
|
||||
set => this.SetValue(HighlightColorProperty, value);
|
||||
}
|
||||
|
||||
private void Grid_MouseEnter(object sender, System.Windows.Input.MouseEventArgs e)
|
||||
{
|
||||
this.Highlighted = true;
|
||||
}
|
||||
|
||||
private void Grid_MouseLeave(object sender, System.Windows.Input.MouseEventArgs e)
|
||||
{
|
||||
this.Highlighted = false;
|
||||
}
|
||||
|
||||
private void Rectangle_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
|
||||
{
|
||||
Clicked?.Invoke(this, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -14,13 +14,27 @@
|
||||
<converters:BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" TriggerValue="True"></converters:BooleanToVisibilityConverter>
|
||||
<converters:BooleanToVisibilityConverter x:Key="ReverseBooleanToVisibilityConverter" TriggerValue="False"></converters:BooleanToVisibilityConverter>
|
||||
</UserControl.Resources>
|
||||
<UserControl.ContextMenu>
|
||||
<ContextMenu>
|
||||
<ContextMenu.Template>
|
||||
<ControlTemplate>
|
||||
<StackPanel Margin="10">
|
||||
<local:OpaqueButton Text="Load build template" Foreground="White" Background="#F0202020" BackgroundOpacity="0.4"
|
||||
Clicked="LoadBuildTemplateButton_Click" FontSize="16" Height="40" Width="200"></local:OpaqueButton>
|
||||
</StackPanel>
|
||||
</ControlTemplate>
|
||||
</ContextMenu.Template>
|
||||
</ContextMenu>
|
||||
</UserControl.ContextMenu>
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="*"></RowDefinition>
|
||||
<RowDefinition Height="auto"></RowDefinition>
|
||||
</Grid.RowDefinitions>
|
||||
<wv2:WebView2 x:Name="WebBrowser" Source="{Binding ElementName=_this, Path=Address, Mode=TwoWay}"></wv2:WebView2>
|
||||
<Grid Grid.Row="1" Background="#80808080">
|
||||
<wv2:WebView2 x:Name="WebBrowser" Source="{Binding ElementName=_this, Path=Address, Mode=TwoWay}"
|
||||
IsEnabled="{Binding ElementName=_this, Path=BrowserSupported, Mode=OneWay}"></wv2:WebView2>
|
||||
<Grid Grid.Row="1" Background="#80808080" IsEnabled="{Binding ElementName=_this, Path=BrowserSupported, Mode=OneWay}"
|
||||
Visibility="{Binding ElementName=_this, Path=ControlsEnabled, Mode=OneWay, Converter={StaticResource ReverseBooleanToVisibilityConverter}}">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="auto"></ColumnDefinition>
|
||||
<ColumnDefinition Width="*"></ColumnDefinition>
|
||||
@@ -51,15 +65,36 @@
|
||||
Grid.Column="1" IsReadOnly="{Binding ElementName=_this, Path=AddressBarReadonly, Mode=OneWay}" Background="Transparent"
|
||||
BorderThickness="1" VerticalAlignment="Center" VerticalContentAlignment="Center"
|
||||
BorderBrush="{Binding ElementName=_this, Path=Foreground, Mode=OneWay}"
|
||||
PreviewKeyDown="TextBox_PreviewKeyDown"></TextBox>
|
||||
PreviewKeyDown="TextBox_PreviewKeyDown"
|
||||
IsEnabled="{Binding ElementName=_this, Path=BrowserSupported, Mode=OneWay}"></TextBox>
|
||||
<StackPanel Grid.Column="2" Orientation="Horizontal">
|
||||
<local:HomeButton Width="30" Height="30" Margin="5"
|
||||
Foreground="{Binding ElementName=_this, Path=Foreground, Mode=OneWay}"
|
||||
IsEnabled="{Binding ElementName=_this, Path=BrowserSupported, Mode=OneWay}"
|
||||
Clicked="HomeButton_Clicked"></local:HomeButton>
|
||||
<local:StarGlyph Height="30" Width="30" Margin="5"
|
||||
Foreground="{Binding ElementName=_this, Path=Foreground, Mode=OneWay}"
|
||||
IsEnabled="{Binding ElementName=_this, Path=BrowserSupported, Mode=OneWay}"
|
||||
Clicked="StarGlyph_Clicked" x:Name="FavoriteButton"></local:StarGlyph>
|
||||
<local:MaximizeButton Height="30" Width="30" Margin="5"
|
||||
Foreground="{Binding ElementName=_this, Path=Foreground, Mode=OneWay}"
|
||||
IsEnabled="{Binding ElementName=_this, Path=BrowserSupported, Mode=OneWay}"
|
||||
Clicked="MaximizeButton_Clicked"></local:MaximizeButton>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
<Grid Grid.RowSpan="2" Background="Gray"
|
||||
Visibility="{Binding ElementName=_this, Path=BrowserSupported, Mode=OneWay,Converter={StaticResource BooleanToVisibilityConverter}}">
|
||||
<StackPanel VerticalAlignment="Center" HorizontalAlignment="Center">
|
||||
<TextBlock Foreground="White" Text="Browser not supported." FontSize="26" TextWrapping="Wrap"></TextBlock>
|
||||
<TextBlock Foreground="White" Text="Download the Evergreen Bootstrapper from here:" FontSize="26" TextWrapping="Wrap" />
|
||||
<TextBox Background="Transparent" BorderBrush="Transparent" BorderThickness="0"
|
||||
Text="https://go.microsoft.com/fwlink/p/?LinkId=2124703"
|
||||
IsReadOnly="True" Margin="0, 0, 0, 30" FontSize="22" Foreground="Blue"
|
||||
PreviewMouseLeftButtonDown="Hyperlink_PreviewMouseLeftButtonDown" Cursor="Hand"
|
||||
TextWrapping="Wrap"></TextBox>
|
||||
<TextBlock Foreground="White" Text="Restart after the installation." FontSize="26" TextWrapping="Wrap" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
|
||||
</Grid>
|
||||
</UserControl>
|
||||
|
||||
@@ -1,8 +1,15 @@
|
||||
using Daybreak.Launch;
|
||||
using Daybreak.Models.Browser;
|
||||
using Daybreak.Models.Builds;
|
||||
using Daybreak.Services.BuildTemplates;
|
||||
using Daybreak.Services.Configuration;
|
||||
using Daybreak.Services.Logging;
|
||||
using Daybreak.Utils;
|
||||
using Microsoft.Web.WebView2.Core;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Extensions;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Extensions;
|
||||
@@ -14,17 +21,37 @@ namespace Daybreak.Controls
|
||||
/// </summary>
|
||||
public partial class ChromiumBrowserWrapper : UserControl
|
||||
{
|
||||
private const string BrowserDownloadLink = "https://developer.microsoft.com/en-us/microsoft-edge/webview2/";
|
||||
|
||||
public readonly static DependencyProperty AddressProperty = DependencyPropertyExtensions.Register<ChromiumBrowserWrapper, string>(nameof(Address));
|
||||
public readonly static DependencyProperty FavoriteAddressProperty = DependencyPropertyExtensions.Register<ChromiumBrowserWrapper, string>(nameof(FavoriteAddress));
|
||||
public readonly static DependencyProperty NavigatingProperty = DependencyPropertyExtensions.Register<ChromiumBrowserWrapper, bool>(nameof(Navigating));
|
||||
public readonly static DependencyProperty BrowserEnabledProperty = DependencyPropertyExtensions.Register<ChromiumBrowserWrapper, bool>(nameof(BrowserEnabled));
|
||||
public readonly static DependencyProperty AddressBarReadonlyProperty = DependencyPropertyExtensions.Register<ChromiumBrowserWrapper, bool>(nameof(AddressBarReadonly));
|
||||
public readonly static DependencyProperty BrowserSupportedProperty = DependencyPropertyExtensions.Register<ChromiumBrowserWrapper, bool>(nameof(BrowserSupported), new PropertyMetadata(true));
|
||||
public readonly static DependencyProperty ControlsEnabledProperty = DependencyPropertyExtensions.Register<ChromiumBrowserWrapper, bool>(nameof(ControlsEnabled), new PropertyMetadata(true));
|
||||
public readonly static DependencyProperty CanNavigateProperty = DependencyPropertyExtensions.Register<ChromiumBrowserWrapper, bool>(nameof(CanNavigate), new PropertyMetadata(true));
|
||||
public readonly static DependencyProperty CanDownloadBuildProperty = DependencyPropertyExtensions.Register<ChromiumBrowserWrapper, bool>(nameof(CanDownloadBuild), new PropertyMetadata(false));
|
||||
|
||||
public event EventHandler<string> FavoriteUriChanged;
|
||||
public event EventHandler MaximizeClicked;
|
||||
public event EventHandler<Build> BuildDecoded;
|
||||
|
||||
private readonly CoreWebView2Environment coreWebView2Environment;
|
||||
private readonly IConfigurationManager configurationManager;
|
||||
private readonly ILogger logger;
|
||||
private readonly IBuildTemplateManager buildTemplateManager;
|
||||
private CoreWebView2Environment coreWebView2Environment;
|
||||
|
||||
public bool CanDownloadBuild
|
||||
{
|
||||
get => this.GetTypedValue<bool>(CanDownloadBuildProperty);
|
||||
set => this.SetTypedValue<bool>(CanDownloadBuildProperty, value);
|
||||
}
|
||||
public bool CanNavigate
|
||||
{
|
||||
get => this.GetTypedValue<bool>(CanNavigateProperty);
|
||||
set => this.SetTypedValue<bool>(CanNavigateProperty, value);
|
||||
}
|
||||
public string Address
|
||||
{
|
||||
get => this.GetTypedValue<string>(AddressProperty);
|
||||
@@ -43,14 +70,31 @@ namespace Daybreak.Controls
|
||||
public bool AddressBarReadonly
|
||||
{
|
||||
get => this.GetTypedValue<bool>(AddressBarReadonlyProperty);
|
||||
private set => this.SetTypedValue<bool>(AddressBarReadonlyProperty, value);
|
||||
set => this.SetTypedValue<bool>(AddressBarReadonlyProperty, value);
|
||||
}
|
||||
public bool BrowserEnabled
|
||||
{
|
||||
get => this.GetTypedValue<bool>(BrowserEnabledProperty);
|
||||
private set => this.SetTypedValue<bool>(BrowserEnabledProperty, value);
|
||||
}
|
||||
public bool BrowserSupported
|
||||
{
|
||||
get => this.GetTypedValue<bool>(BrowserSupportedProperty);
|
||||
private set => this.SetTypedValue<bool>(BrowserSupportedProperty, value);
|
||||
}
|
||||
public bool ControlsEnabled
|
||||
{
|
||||
get => this.GetTypedValue<bool>(ControlsEnabledProperty);
|
||||
set => this.SetTypedValue<bool>(ControlsEnabledProperty, value);
|
||||
}
|
||||
|
||||
public ChromiumBrowserWrapper()
|
||||
{
|
||||
this.coreWebView2Environment = Launcher.ApplicationServiceManager.GetService<CoreWebView2Environment>();
|
||||
this.configurationManager = Launcher.ApplicationServiceManager.GetService<IConfigurationManager>();
|
||||
this.logger = Launcher.ApplicationServiceManager.GetService<ILogger>();
|
||||
this.buildTemplateManager = Launcher.ApplicationServiceManager.GetService<IBuildTemplateManager>();
|
||||
this.InitializeComponent();
|
||||
this.InitializeEnvironment();
|
||||
this.InitializeBrowser();
|
||||
}
|
||||
|
||||
@@ -63,18 +107,80 @@ namespace Daybreak.Controls
|
||||
}
|
||||
}
|
||||
|
||||
public void ReinitializeBrowser()
|
||||
public async void ReinitializeBrowser()
|
||||
{
|
||||
this.InitializeBrowser();
|
||||
await this.InitializeBrowser();
|
||||
}
|
||||
|
||||
private async void InitializeBrowser()
|
||||
private void InitializeEnvironment()
|
||||
{
|
||||
await this.WebBrowser.EnsureCoreWebView2Async(this.coreWebView2Environment);
|
||||
this.AddressBarReadonly = this.configurationManager.GetConfiguration().AddressBarReadonly;
|
||||
this.WebBrowser.CoreWebView2.NewWindowRequested += (browser, args) => args.Handled = true;
|
||||
this.WebBrowser.NavigationStarting += (browser, args) => this.Navigating = true;
|
||||
this.WebBrowser.NavigationCompleted += (browser, args) => this.Navigating = false;
|
||||
if (this.configurationManager.GetConfiguration().BrowsersEnabled is false)
|
||||
{
|
||||
this.BrowserSupported = false;
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
this.coreWebView2Environment = System.Extensions.TaskExtensions.RunSync(() => CoreWebView2Environment.CreateAsync(null, "BrowserData", null));
|
||||
this.BrowserSupported = true;
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
this.logger.LogWarning($"Browser initialization failed. Details: {e}");
|
||||
this.BrowserSupported = false;
|
||||
}
|
||||
}
|
||||
|
||||
private async Task InitializeBrowser()
|
||||
{
|
||||
if (this.BrowserSupported is true)
|
||||
{
|
||||
await this.WebBrowser.EnsureCoreWebView2Async(this.coreWebView2Environment);
|
||||
this.AddressBarReadonly = this.configurationManager.GetConfiguration().AddressBarReadonly;
|
||||
this.CanDownloadBuild = this.configurationManager.GetConfiguration().ExperimentalFeatures.DynamicBuildLoading;
|
||||
this.WebBrowser.CoreWebView2.NewWindowRequested += (browser, args) => args.Handled = true;
|
||||
this.WebBrowser.NavigationStarting += (browser, args) =>
|
||||
{
|
||||
if (this.CanNavigate is false && args.Uri != this.Address)
|
||||
{
|
||||
args.Cancel = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.Navigating = true;
|
||||
}
|
||||
};
|
||||
this.WebBrowser.NavigationCompleted += (browser, args) => this.Navigating = false;
|
||||
this.WebBrowser.WebMessageReceived += this.CoreWebView2_WebMessageReceived;
|
||||
this.WebBrowser.CoreWebView2.Settings.AreDevToolsEnabled = false;
|
||||
this.WebBrowser.CoreWebView2.Settings.AreDefaultContextMenusEnabled = false;
|
||||
if (this.CanDownloadBuild)
|
||||
{
|
||||
await this.WebBrowser.CoreWebView2.AddScriptToExecuteOnDocumentCreatedAsync(Scripts.SendSelectionOnContextMenu);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async void RetryInitializeButton_Clicked(object sender, EventArgs e)
|
||||
{
|
||||
this.InitializeEnvironment();
|
||||
try
|
||||
{
|
||||
await this.InitializeBrowser();
|
||||
}
|
||||
catch
|
||||
{
|
||||
this.BrowserSupported = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void Hyperlink_PreviewMouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
|
||||
{
|
||||
if (Uri.TryCreate(BrowserDownloadLink, UriKind.Absolute, out var uri))
|
||||
{
|
||||
Process.Start("explorer.exe", uri.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
private void TextBox_PreviewKeyDown(object sender, System.Windows.Input.KeyEventArgs e)
|
||||
@@ -94,9 +200,60 @@ namespace Daybreak.Controls
|
||||
}
|
||||
}
|
||||
|
||||
private void CoreWebView2_WebMessageReceived(object sender, CoreWebView2WebMessageReceivedEventArgs args)
|
||||
{
|
||||
BrowserPayload payload = default;
|
||||
try
|
||||
{
|
||||
payload = args.WebMessageAsJson.Deserialize<BrowserPayload>();
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
this.logger.LogError(e);
|
||||
}
|
||||
if (payload?.Key == BrowserPayload.PayloadKeys.ContextMenu)
|
||||
{
|
||||
var contextMenuPayload = args.WebMessageAsJson.Deserialize<BrowserPayload<OnContextMenuPayload>>();
|
||||
var maybeTemplate = contextMenuPayload.Value.Selection;
|
||||
if (string.IsNullOrWhiteSpace(maybeTemplate))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.buildTemplateManager.IsTemplate(maybeTemplate) is false)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Task.Run(() =>
|
||||
{
|
||||
try
|
||||
{
|
||||
var build = this.buildTemplateManager.DecodeTemplate(maybeTemplate);
|
||||
this.Dispatcher.Invoke(() =>
|
||||
{
|
||||
this.ContextMenu.DataContext = build;
|
||||
this.ContextMenu.IsOpen = true;
|
||||
});
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
this.logger.LogWarning($"Exception when decoding template {maybeTemplate}. Details {e}");
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void LoadBuildTemplateButton_Click(object sender, EventArgs e)
|
||||
{
|
||||
var build = this.ContextMenu.DataContext.As<Build>();
|
||||
this.ContextMenu.IsOpen = false;
|
||||
this.BuildDecoded?.Invoke(this, build);
|
||||
}
|
||||
|
||||
private void UserControl_Unloaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
this.WebBrowser.Dispose();
|
||||
this.WebBrowser?.Dispose();
|
||||
}
|
||||
|
||||
private void BackButton_Clicked(object sender, EventArgs e)
|
||||
@@ -128,6 +285,11 @@ namespace Daybreak.Controls
|
||||
this.FavoriteUriChanged?.Invoke(this, this.FavoriteAddress);
|
||||
}
|
||||
|
||||
private void HomeButton_Clicked(object sender, EventArgs e)
|
||||
{
|
||||
this.WebBrowser.CoreWebView2.Navigate(this.FavoriteAddress);
|
||||
}
|
||||
|
||||
private void MaximizeButton_Clicked(object sender, EventArgs e)
|
||||
{
|
||||
this.MaximizeClicked?.Invoke(this, e);
|
||||
|
||||
@@ -0,0 +1,553 @@
|
||||
<UserControl x:Class="Daybreak.Controls.CircularLoadingWidget"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="clr-namespace:Daybreak.Controls"
|
||||
Height="Auto" Width="Auto">
|
||||
<UserControl.Resources>
|
||||
<Storyboard x:Key="ProgressAnimation" RepeatBehavior="Forever">
|
||||
<ColorAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="block" Storyboard.TargetProperty="(UIElement.OpacityMask).(SolidColorBrush.Color)">
|
||||
<SplineColorKeyFrame KeyTime="00:00:00" Value="Black"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:00.2290000" Value="#EF000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:00.4590000" Value="#E2000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:00.6880000" Value="#D3000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:00.9180000" Value="#C6000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:01.1470000" Value="#B7000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:01.3760000" Value="#AA000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:01.6060000" Value="#9B000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:01.8350000" Value="#8E000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:02.0650000" Value="#7F000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:02.2940000" Value="#72000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:02.5240000" Value="#63000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:02.7530000" Value="#56000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:02.9820000" Value="#3D000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:03.2120000" Value="#26000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:03.4410000" Value="#19000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:03.6710000" Value="#0C000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:03.9000000" Value="#00000000"/>
|
||||
</ColorAnimationUsingKeyFrames>
|
||||
<ColorAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="block17" Storyboard.TargetProperty="(UIElement.OpacityMask).(SolidColorBrush.Color)">
|
||||
<SplineColorKeyFrame KeyTime="00:00:00" Value="#EF000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:00.2290000" Value="#E2000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:00.4590000" Value="#D3000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:00.6880000" Value="#C6000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:00.9180000" Value="#B7000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:01.1470000" Value="#AA000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:01.3760000" Value="#9B000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:01.6060000" Value="#8E000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:01.8350000" Value="#7F000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:02.0650000" Value="#72000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:02.2940000" Value="#63000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:02.5240000" Value="#56000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:02.7530000" Value="#3D000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:02.9820000" Value="#26000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:03.2120000" Value="#19000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:03.4410000" Value="#0C000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:03.6710000" Value="#00000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:03.9000000" Value="Black"/>
|
||||
</ColorAnimationUsingKeyFrames>
|
||||
<ColorAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="block16" Storyboard.TargetProperty="(UIElement.OpacityMask).(SolidColorBrush.Color)">
|
||||
<SplineColorKeyFrame KeyTime="00:00:00" Value="#E2000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:00.2290000" Value="#D3000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:00.4590000" Value="#C6000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:00.6880000" Value="#B7000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:00.9180000" Value="#AA000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:01.1470000" Value="#9B000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:01.3760000" Value="#8E000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:01.6060000" Value="#7F000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:01.8350000" Value="#72000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:02.0650000" Value="#63000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:02.2940000" Value="#56000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:02.5240000" Value="#3D000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:02.7530000" Value="#26000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:02.9820000" Value="#19000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:03.2120000" Value="#0C000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:03.4410000" Value="#00000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:03.6710000" Value="Black"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:03.9000000" Value="#EF000000"/>
|
||||
</ColorAnimationUsingKeyFrames>
|
||||
<ColorAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="block15" Storyboard.TargetProperty="(UIElement.OpacityMask).(SolidColorBrush.Color)">
|
||||
<SplineColorKeyFrame KeyTime="00:00:00" Value="#D3000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:00.2290000" Value="#C6000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:00.4590000" Value="#B7000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:00.6880000" Value="#AA000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:00.9180000" Value="#9B000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:01.1470000" Value="#8E000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:01.3760000" Value="#7F000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:01.6060000" Value="#72000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:01.8350000" Value="#63000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:02.0650000" Value="#56000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:02.2940000" Value="#3D000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:02.5240000" Value="#26000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:02.7530000" Value="#19000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:02.9820000" Value="#0C000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:03.2120000" Value="#00000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:03.4410000" Value="Black"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:03.6710000" Value="#EF000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:03.9000000" Value="#E2000000"/>
|
||||
</ColorAnimationUsingKeyFrames>
|
||||
<ColorAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="block14" Storyboard.TargetProperty="(UIElement.OpacityMask).(SolidColorBrush.Color)">
|
||||
<SplineColorKeyFrame KeyTime="00:00:00" Value="#C6000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:00.2290000" Value="#B7000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:00.4590000" Value="#AA000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:00.6880000" Value="#9B000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:00.9180000" Value="#8E000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:01.1470000" Value="#7F000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:01.3760000" Value="#72000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:01.6060000" Value="#63000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:01.8350000" Value="#56000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:02.0650000" Value="#3D000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:02.2940000" Value="#26000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:02.5240000" Value="#19000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:02.7530000" Value="#0C000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:02.9820000" Value="#00000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:03.2120000" Value="Black"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:03.4410000" Value="#EF000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:03.6710000" Value="#E2000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:03.9000000" Value="#D3000000"/>
|
||||
</ColorAnimationUsingKeyFrames>
|
||||
<ColorAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="block13" Storyboard.TargetProperty="(UIElement.OpacityMask).(SolidColorBrush.Color)">
|
||||
<SplineColorKeyFrame KeyTime="00:00:00" Value="#B7000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:00.2290000" Value="#AA000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:00.4590000" Value="#9B000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:00.6880000" Value="#8E000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:00.9180000" Value="#7F000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:01.1470000" Value="#72000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:01.3760000" Value="#63000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:01.6060000" Value="#56000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:01.8350000" Value="#3D000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:02.0650000" Value="#26000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:02.2940000" Value="#19000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:02.5240000" Value="#0C000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:02.7530000" Value="#00000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:02.9820000" Value="Black"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:03.2120000" Value="#EF000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:03.4410000" Value="#E2000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:03.6710000" Value="#D3000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:03.9000000" Value="#C6000000"/>
|
||||
</ColorAnimationUsingKeyFrames>
|
||||
<ColorAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="block12" Storyboard.TargetProperty="(UIElement.OpacityMask).(SolidColorBrush.Color)">
|
||||
<SplineColorKeyFrame KeyTime="00:00:00" Value="#AA000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:00.2290000" Value="#9B000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:00.4590000" Value="#8E000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:00.6880000" Value="#7F000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:00.9180000" Value="#72000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:01.1470000" Value="#63000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:01.3760000" Value="#56000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:01.6060000" Value="#3D000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:01.8350000" Value="#26000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:02.0650000" Value="#19000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:02.2940000" Value="#0C000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:02.5240000" Value="#00000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:02.7530000" Value="Black"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:02.9820000" Value="#EF000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:03.2120000" Value="#E2000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:03.4410000" Value="#D3000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:03.6710000" Value="#C6000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:03.9000000" Value="#B7000000"/>
|
||||
</ColorAnimationUsingKeyFrames>
|
||||
<ColorAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="block11" Storyboard.TargetProperty="(UIElement.OpacityMask).(SolidColorBrush.Color)">
|
||||
<SplineColorKeyFrame KeyTime="00:00:00" Value="#9B000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:00.2290000" Value="#8E000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:00.4590000" Value="#7F000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:00.6880000" Value="#72000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:00.9180000" Value="#63000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:01.1470000" Value="#56000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:01.3760000" Value="#3D000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:01.6060000" Value="#26000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:01.8350000" Value="#19000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:02.0650000" Value="#0C000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:02.2940000" Value="#00000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:02.5240000" Value="Black"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:02.7530000" Value="#EF000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:02.9820000" Value="#E2000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:03.2120000" Value="#D3000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:03.4410000" Value="#C6000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:03.6710000" Value="#B7000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:03.9000000" Value="#AA000000"/>
|
||||
</ColorAnimationUsingKeyFrames>
|
||||
<ColorAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="block10" Storyboard.TargetProperty="(UIElement.OpacityMask).(SolidColorBrush.Color)">
|
||||
<SplineColorKeyFrame KeyTime="00:00:00" Value="#8E000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:00.2290000" Value="#7F000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:00.4590000" Value="#72000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:00.6880000" Value="#63000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:00.9180000" Value="#56000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:01.1470000" Value="#3D000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:01.3760000" Value="#23000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:01.6060000" Value="#19000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:01.8350000" Value="#0C000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:02.0650000" Value="#00000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:02.2940000" Value="Black"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:02.5240000" Value="#EF000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:02.7530000" Value="#E2000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:02.9820000" Value="#D3000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:03.2120000" Value="#C6000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:03.4410000" Value="#B7000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:03.6710000" Value="#AA000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:03.9000000" Value="#9B000000"/>
|
||||
</ColorAnimationUsingKeyFrames>
|
||||
<ColorAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="block9" Storyboard.TargetProperty="(UIElement.OpacityMask).(SolidColorBrush.Color)">
|
||||
<SplineColorKeyFrame KeyTime="00:00:00" Value="#7F000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:00.2290000" Value="#72000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:00.4590000" Value="#63000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:00.6880000" Value="#56000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:00.9180000" Value="#3D000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:01.1470000" Value="#26000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:01.3760000" Value="#19000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:01.6060000" Value="#0C000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:01.8350000" Value="#00000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:02.0650000" Value="Black"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:02.2940000" Value="#EF000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:02.5240000" Value="#E2000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:02.7530000" Value="#D3000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:02.9820000" Value="#C6000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:03.2120000" Value="#B7000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:03.4410000" Value="#AA000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:03.6710000" Value="#9B000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:03.9000000" Value="#91000000"/>
|
||||
</ColorAnimationUsingKeyFrames>
|
||||
<ColorAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="block8" Storyboard.TargetProperty="(UIElement.OpacityMask).(SolidColorBrush.Color)">
|
||||
<SplineColorKeyFrame KeyTime="00:00:00" Value="#72000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:00.2290000" Value="#63000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:00.4590000" Value="#56000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:00.6880000" Value="#3D000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:00.9180000" Value="#26000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:01.1470000" Value="#19000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:01.3760000" Value="#0C000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:01.6060000" Value="#00000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:01.8350000" Value="Black"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:02.0650000" Value="#EF000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:02.2940000" Value="#E2000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:02.5240000" Value="#D3000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:02.7530000" Value="#C6000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:02.9820000" Value="#B7000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:03.2120000" Value="#AA000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:03.4410000" Value="#9B000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:03.6710000" Value="#91000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:03.9000000" Value="#7F000000"/>
|
||||
</ColorAnimationUsingKeyFrames>
|
||||
<ColorAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="block7" Storyboard.TargetProperty="(UIElement.OpacityMask).(SolidColorBrush.Color)">
|
||||
<SplineColorKeyFrame KeyTime="00:00:00" Value="#63000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:00.2290000" Value="#56000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:00.4590000" Value="#3D000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:00.6880000" Value="#26000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:00.9180000" Value="#19000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:01.1470000" Value="#0C000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:01.3760000" Value="#00000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:01.6060000" Value="Black"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:01.8350000" Value="#EF000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:02.0650000" Value="#E2000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:02.2940000" Value="#D3000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:02.5240000" Value="#C6000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:02.7530000" Value="#B7000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:02.9820000" Value="#AA000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:03.2120000" Value="#9B000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:03.4410000" Value="#91000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:03.6710000" Value="#7F000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:03.9000000" Value="#72000000"/>
|
||||
</ColorAnimationUsingKeyFrames>
|
||||
<ColorAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="block6" Storyboard.TargetProperty="(UIElement.OpacityMask).(SolidColorBrush.Color)">
|
||||
<SplineColorKeyFrame KeyTime="00:00:00" Value="#56000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:00.2290000" Value="#3D000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:00.4590000" Value="#26000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:00.6880000" Value="#19000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:00.9180000" Value="#0C000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:01.1470000" Value="#00000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:01.3760000" Value="Black"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:01.6060000" Value="#EF000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:01.8350000" Value="#E2000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:02.0650000" Value="#D3000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:02.2940000" Value="#C6000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:02.5240000" Value="#B7000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:02.7530000" Value="#AA000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:02.9820000" Value="#9B000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:03.2120000" Value="#91000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:03.4410000" Value="#7F000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:03.6710000" Value="#72000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:03.9000000" Value="#63000000"/>
|
||||
</ColorAnimationUsingKeyFrames>
|
||||
<ColorAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="block5" Storyboard.TargetProperty="(UIElement.OpacityMask).(SolidColorBrush.Color)">
|
||||
<SplineColorKeyFrame KeyTime="00:00:00" Value="#3D000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:00.2290000" Value="#26000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:00.4590000" Value="#19000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:00.6880000" Value="#0C000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:00.9180000" Value="#00000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:01.1470000" Value="Black"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:01.3760000" Value="#EF000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:01.6060000" Value="#E2000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:01.8350000" Value="#D3000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:02.0650000" Value="#C6000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:02.2940000" Value="#B7000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:02.5240000" Value="#AA000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:02.7530000" Value="#9B000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:02.9820000" Value="#91000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:03.2120000" Value="#7F000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:03.4410000" Value="#72000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:03.6710000" Value="#63000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:03.9000000" Value="#56000000"/>
|
||||
</ColorAnimationUsingKeyFrames>
|
||||
<ColorAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="block4" Storyboard.TargetProperty="(UIElement.OpacityMask).(SolidColorBrush.Color)">
|
||||
<SplineColorKeyFrame KeyTime="00:00:00" Value="#26000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:00.2290000" Value="#19000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:00.4590000" Value="#0C000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:00.6880000" Value="#00000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:00.9180000" Value="Black"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:01.1470000" Value="#EF000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:01.3760000" Value="#E2000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:01.6060000" Value="#D3000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:01.8350000" Value="#C6000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:02.0650000" Value="#B7000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:02.2940000" Value="#AA000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:02.5240000" Value="#9B000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:02.7530000" Value="#91000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:02.9820000" Value="#7F000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:03.2120000" Value="#72000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:03.4410000" Value="#63000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:03.6710000" Value="#56000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:03.9000000" Value="#3D000000"/>
|
||||
</ColorAnimationUsingKeyFrames>
|
||||
<ColorAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="block3" Storyboard.TargetProperty="(UIElement.OpacityMask).(SolidColorBrush.Color)">
|
||||
<SplineColorKeyFrame KeyTime="00:00:00" Value="#19000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:00.2290000" Value="#0C000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:00.4590000" Value="#00000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:00.6880000" Value="Black"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:00.9180000" Value="#EF000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:01.1470000" Value="#E2000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:01.3760000" Value="#D3000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:01.6060000" Value="#C6000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:01.8350000" Value="#B7000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:02.0650000" Value="#AA000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:02.2940000" Value="#9B000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:02.5240000" Value="#91000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:02.7530000" Value="#7F000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:02.9820000" Value="#72000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:03.2120000" Value="#63000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:03.4410000" Value="#56000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:03.6710000" Value="#3D000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:03.9000000" Value="#26000000"/>
|
||||
</ColorAnimationUsingKeyFrames>
|
||||
<ColorAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="block2" Storyboard.TargetProperty="(UIElement.OpacityMask).(SolidColorBrush.Color)">
|
||||
<SplineColorKeyFrame KeyTime="00:00:00" Value="#0C000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:00.2290000" Value="#00000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:00.4590000" Value="Black"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:00.6880000" Value="#EF000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:00.9180000" Value="#E2000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:01.1470000" Value="#D3000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:01.3760000" Value="#C6000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:01.6060000" Value="#B7000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:01.8350000" Value="#AA000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:02.0650000" Value="#9B000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:02.2940000" Value="#91000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:02.5240000" Value="#7F000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:02.7530000" Value="#72000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:02.9820000" Value="#63000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:03.2120000" Value="#56000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:03.4410000" Value="#3D000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:03.6710000" Value="#26000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:03.9000000" Value="#19000000"/>
|
||||
</ColorAnimationUsingKeyFrames>
|
||||
<ColorAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="block1" Storyboard.TargetProperty="(UIElement.OpacityMask).(SolidColorBrush.Color)">
|
||||
<SplineColorKeyFrame KeyTime="00:00:00" Value="#00000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:00.2290000" Value="Black"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:00.4590000" Value="#EF000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:00.6880000" Value="#E2000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:00.9180000" Value="#D3000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:01.1470000" Value="#C6000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:01.3760000" Value="#B7000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:01.6060000" Value="#AA000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:01.8350000" Value="#9B000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:02.0650000" Value="#8E000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:02.2940000" Value="#7F000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:02.5240000" Value="#72000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:02.7530000" Value="#63000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:02.9820000" Value="#56000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:03.2120000" Value="#3D000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:03.4410000" Value="#26000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:03.6710000" Value="#19000000"/>
|
||||
<SplineColorKeyFrame KeyTime="00:00:03.9000000" Value="#0C000000"/>
|
||||
</ColorAnimationUsingKeyFrames>
|
||||
</Storyboard>
|
||||
</UserControl.Resources>
|
||||
<UserControl.Triggers>
|
||||
<EventTrigger RoutedEvent="FrameworkElement.Loaded">
|
||||
<BeginStoryboard x:Name="ProgressAnimation_BeginStoryboard" Storyboard="{StaticResource ProgressAnimation}"/>
|
||||
</EventTrigger>
|
||||
</UserControl.Triggers>
|
||||
|
||||
<Viewbox>
|
||||
<Canvas x:Name="LayoutRoot" VerticalAlignment="Top" Height="88" Width="88">
|
||||
<Grid Width="10.734" Height="10.004" Canvas.Left="38.614" Canvas.Top="0.331">
|
||||
<Rectangle Fill="White" x:Name="block" RenderTransformOrigin="0.5,4.3689" OpacityMask="#00000000" VerticalAlignment="Top" Height="10.004">
|
||||
<Rectangle.RenderTransform>
|
||||
<TransformGroup>
|
||||
<ScaleTransform/>
|
||||
<SkewTransform/>
|
||||
<RotateTransform Angle="180"/>
|
||||
<TranslateTransform/>
|
||||
</TransformGroup>
|
||||
</Rectangle.RenderTransform>
|
||||
</Rectangle>
|
||||
<Rectangle x:Name="block1" Fill="White" RenderTransformOrigin="0.5,4.3689" OpacityMask="#0C000000" VerticalAlignment="Top" Height="10.004">
|
||||
<Rectangle.RenderTransform>
|
||||
<TransformGroup>
|
||||
<ScaleTransform ScaleX="0.99999999999999989" ScaleY="0.99999999999999989"/>
|
||||
<SkewTransform/>
|
||||
<RotateTransform Angle="-160"/>
|
||||
<TranslateTransform/>
|
||||
</TransformGroup>
|
||||
</Rectangle.RenderTransform>
|
||||
</Rectangle>
|
||||
<Rectangle x:Name="block2" Fill="White" RenderTransformOrigin="0.5,4.3689" OpacityMask="#19000000" VerticalAlignment="Top" Height="10.004">
|
||||
<Rectangle.RenderTransform>
|
||||
<TransformGroup>
|
||||
<ScaleTransform/>
|
||||
<SkewTransform/>
|
||||
<RotateTransform Angle="-140"/>
|
||||
<TranslateTransform/>
|
||||
</TransformGroup>
|
||||
</Rectangle.RenderTransform>
|
||||
</Rectangle>
|
||||
<Rectangle x:Name="block3" Fill="White" RenderTransformOrigin="0.5,4.3689" OpacityMask="#26000000" VerticalAlignment="Top" Height="10.004">
|
||||
<Rectangle.RenderTransform>
|
||||
<TransformGroup>
|
||||
<ScaleTransform ScaleX="0.99999999999999989" ScaleY="0.99999999999999989"/>
|
||||
<SkewTransform/>
|
||||
<RotateTransform Angle="-119.99999999999999"/>
|
||||
<TranslateTransform/>
|
||||
</TransformGroup>
|
||||
</Rectangle.RenderTransform>
|
||||
</Rectangle>
|
||||
<Rectangle x:Name="block4" Fill="White" RenderTransformOrigin="0.5,4.3689" OpacityMask="#3D000000" VerticalAlignment="Top" Height="10.004">
|
||||
<Rectangle.RenderTransform>
|
||||
<TransformGroup>
|
||||
<ScaleTransform ScaleX="0.99999999999999989" ScaleY="0.99999999999999989"/>
|
||||
<SkewTransform/>
|
||||
<RotateTransform Angle="-100"/>
|
||||
<TranslateTransform/>
|
||||
</TransformGroup>
|
||||
</Rectangle.RenderTransform>
|
||||
</Rectangle>
|
||||
<Rectangle x:Name="block5" Fill="White" RenderTransformOrigin="0.5,4.3689" OpacityMask="#56000000" VerticalAlignment="Top" Height="10.004">
|
||||
<Rectangle.RenderTransform>
|
||||
<TransformGroup>
|
||||
<ScaleTransform ScaleX="0.99999999999999989" ScaleY="0.99999999999999989"/>
|
||||
<SkewTransform/>
|
||||
<RotateTransform Angle="-80"/>
|
||||
<TranslateTransform/>
|
||||
</TransformGroup>
|
||||
</Rectangle.RenderTransform>
|
||||
</Rectangle>
|
||||
<Rectangle x:Name="block6" Fill="White" RenderTransformOrigin="0.5,4.3689" OpacityMask="#64000000" VerticalAlignment="Top" Height="10.004">
|
||||
<Rectangle.RenderTransform>
|
||||
<TransformGroup>
|
||||
<ScaleTransform/>
|
||||
<SkewTransform/>
|
||||
<RotateTransform Angle="-59.999999999999993"/>
|
||||
<TranslateTransform/>
|
||||
</TransformGroup>
|
||||
</Rectangle.RenderTransform>
|
||||
</Rectangle>
|
||||
<Rectangle x:Name="block7" Fill="White" RenderTransformOrigin="0.5,4.3689" OpacityMask="#72000000" VerticalAlignment="Top" Height="10.004">
|
||||
<Rectangle.RenderTransform>
|
||||
<TransformGroup>
|
||||
<ScaleTransform ScaleX="0.99999999999999989" ScaleY="0.99999999999999989"/>
|
||||
<SkewTransform/>
|
||||
<RotateTransform Angle="-40"/>
|
||||
<TranslateTransform/>
|
||||
</TransformGroup>
|
||||
</Rectangle.RenderTransform>
|
||||
</Rectangle>
|
||||
<Rectangle x:Name="block8" Fill="White" RenderTransformOrigin="0.5,4.3689" OpacityMask="#80000000" VerticalAlignment="Top" Height="10.004">
|
||||
<Rectangle.RenderTransform>
|
||||
<TransformGroup>
|
||||
<ScaleTransform/>
|
||||
<SkewTransform/>
|
||||
<RotateTransform Angle="-19.999999999999996"/>
|
||||
<TranslateTransform/>
|
||||
</TransformGroup>
|
||||
</Rectangle.RenderTransform>
|
||||
</Rectangle>
|
||||
<Rectangle x:Name="block9" Fill="White" OpacityMask="#8E000000" RenderTransformOrigin="0.5,4.3689" VerticalAlignment="Top" Height="10.004"/>
|
||||
<Rectangle x:Name="block10" Fill="White" RenderTransformOrigin="0.5,4.3689" OpacityMask="#9C000000" VerticalAlignment="Top" Height="10.004">
|
||||
<Rectangle.RenderTransform>
|
||||
<TransformGroup>
|
||||
<ScaleTransform/>
|
||||
<SkewTransform/>
|
||||
<RotateTransform Angle="19.999999999999996"/>
|
||||
<TranslateTransform/>
|
||||
</TransformGroup>
|
||||
</Rectangle.RenderTransform>
|
||||
</Rectangle>
|
||||
<Rectangle x:Name="block11" Fill="White" RenderTransformOrigin="0.5,4.3689" OpacityMask="#AA000000" VerticalAlignment="Top" Height="10.004">
|
||||
<Rectangle.RenderTransform>
|
||||
<TransformGroup>
|
||||
<ScaleTransform ScaleX="0.99999999999999989" ScaleY="0.99999999999999989"/>
|
||||
<SkewTransform/>
|
||||
<RotateTransform Angle="40"/>
|
||||
<TranslateTransform/>
|
||||
</TransformGroup>
|
||||
</Rectangle.RenderTransform>
|
||||
</Rectangle>
|
||||
<Rectangle x:Name="block12" Fill="White" RenderTransformOrigin="0.5,4.3689" OpacityMask="#B8000000" VerticalAlignment="Top" Height="10.004">
|
||||
<Rectangle.RenderTransform>
|
||||
<TransformGroup>
|
||||
<ScaleTransform/>
|
||||
<SkewTransform/>
|
||||
<RotateTransform Angle="59.999999999999993"/>
|
||||
<TranslateTransform/>
|
||||
</TransformGroup>
|
||||
</Rectangle.RenderTransform>
|
||||
</Rectangle>
|
||||
<Rectangle x:Name="block13" Fill="White" RenderTransformOrigin="0.5,4.3689" OpacityMask="#C6000000" VerticalAlignment="Top" Height="10.004">
|
||||
<Rectangle.RenderTransform>
|
||||
<TransformGroup>
|
||||
<ScaleTransform ScaleX="0.99999999999999989" ScaleY="0.99999999999999989"/>
|
||||
<SkewTransform/>
|
||||
<RotateTransform Angle="80"/>
|
||||
<TranslateTransform/>
|
||||
</TransformGroup>
|
||||
</Rectangle.RenderTransform>
|
||||
</Rectangle>
|
||||
<Rectangle x:Name="block14" Fill="White" RenderTransformOrigin="0.5,4.3689" OpacityMask="#D4000000" VerticalAlignment="Top" Height="10.004">
|
||||
<Rectangle.RenderTransform>
|
||||
<TransformGroup>
|
||||
<ScaleTransform ScaleX="0.99999999999999989" ScaleY="0.99999999999999989"/>
|
||||
<SkewTransform/>
|
||||
<RotateTransform Angle="100"/>
|
||||
<TranslateTransform/>
|
||||
</TransformGroup>
|
||||
</Rectangle.RenderTransform>
|
||||
</Rectangle>
|
||||
<Rectangle x:Name="block15" Fill="White" RenderTransformOrigin="0.5,4.3689" OpacityMask="#E2000000" VerticalAlignment="Top" Height="10.004">
|
||||
<Rectangle.RenderTransform>
|
||||
<TransformGroup>
|
||||
<ScaleTransform ScaleX="0.99999999999999989" ScaleY="0.99999999999999989"/>
|
||||
<SkewTransform/>
|
||||
<RotateTransform Angle="119.99999999999999"/>
|
||||
<TranslateTransform/>
|
||||
</TransformGroup>
|
||||
</Rectangle.RenderTransform>
|
||||
</Rectangle>
|
||||
<Rectangle x:Name="block16" Fill="White" RenderTransformOrigin="0.5,4.3689" OpacityMask="#F0000000" VerticalAlignment="Top" Height="10.004">
|
||||
<Rectangle.RenderTransform>
|
||||
<TransformGroup>
|
||||
<ScaleTransform/>
|
||||
<SkewTransform/>
|
||||
<RotateTransform Angle="140"/>
|
||||
<TranslateTransform/>
|
||||
</TransformGroup>
|
||||
</Rectangle.RenderTransform>
|
||||
</Rectangle>
|
||||
<Rectangle x:Name="block17" Fill="White" RenderTransformOrigin="0.5,4.3689" OpacityMask="Black" VerticalAlignment="Top" Height="10.004">
|
||||
<Rectangle.RenderTransform>
|
||||
<TransformGroup>
|
||||
<ScaleTransform ScaleX="0.99999999999999989" ScaleY="0.99999999999999989"/>
|
||||
<SkewTransform/>
|
||||
<RotateTransform Angle="160"/>
|
||||
<TranslateTransform/>
|
||||
</TransformGroup>
|
||||
</Rectangle.RenderTransform>
|
||||
</Rectangle>
|
||||
</Grid>
|
||||
</Canvas>
|
||||
</Viewbox>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,32 @@
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace Daybreak.Controls
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for CircularLoadingWidget.xaml
|
||||
/// </summary>
|
||||
public partial class CircularLoadingWidget : UserControl
|
||||
{
|
||||
public CircularLoadingWidget()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
base.OnPropertyChanged(e);
|
||||
if (e.Property == IsEnabledProperty)
|
||||
{
|
||||
if (e.NewValue is true)
|
||||
{
|
||||
this.ProgressAnimation_BeginStoryboard.Storyboard.Pause();
|
||||
}
|
||||
else
|
||||
{
|
||||
this.ProgressAnimation_BeginStoryboard.Storyboard.Resume();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
<UserControl x:Class="Daybreak.Controls.FilePickerGlyph"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:Daybreak.Controls"
|
||||
mc:Ignorable="d"
|
||||
x:Name="_this"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<Grid>
|
||||
<Rectangle x:Name="BackgroundEllipse" Fill="{Binding ElementName=_this, Path=Foreground, Mode=OneWay}" Visibility="Visible" Opacity="0.1" />
|
||||
<Viewbox>
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Ellipse Fill="{Binding ElementName=_this, Path=Foreground, Mode=OneWay}" Height="1" Width="1"></Ellipse>
|
||||
<Ellipse Fill="{Binding ElementName=_this, Path=Foreground, Mode=OneWay}" Height="1" Width="1"></Ellipse>
|
||||
<Ellipse Fill="{Binding ElementName=_this, Path=Foreground, Mode=OneWay}" Height="1" Width="1"></Ellipse>
|
||||
</StackPanel>
|
||||
</Viewbox>
|
||||
<Rectangle Fill="Transparent" MouseEnter="Ellipse_MouseEnter" MouseLeave="Ellipse_MouseLeave" MouseLeftButtonDown="Ellipse_MouseLeftButtonDown"></Rectangle>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,18 @@
|
||||
<UserControl x:Class="Daybreak.Controls.AvatarGlyph"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:Daybreak.Controls"
|
||||
mc:Ignorable="d"
|
||||
x:Name="_this"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<Viewbox>
|
||||
<Grid>
|
||||
<Path Fill="{Binding ElementName=_this, Path=Foreground, Mode=OneWay}"
|
||||
Data="m5.7,104.4c10.6,-10.6 24.6,-16.4 39.6,-16.4s29,5.8 39.6,16.4l5.7,-5.7c-12.1,-12 -28.2,-18.7 -45.3,-18.7s-33.2,6.7 -45.3,18.7l5.7,5.7z"></Path>
|
||||
<Path Fill="{Binding ElementName=_this, Path=Foreground, Mode=OneWay}"
|
||||
Data="m11.3,34c0,18.7 15.3,34 34,34s34,-15.3 34,-34s-15.3,-34 -34,-34s-34,15.3 -34,34zm60,0c0,14.3 -11.7,26 -26,26s-26,-11.7 -26,-26s11.7,-26 26,-26s26,11.7 26,26z"></Path>
|
||||
</Grid>
|
||||
</Viewbox>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,28 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
using System.Windows.Navigation;
|
||||
using System.Windows.Shapes;
|
||||
|
||||
namespace Daybreak.Controls
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for AvatarGlyph.xaml
|
||||
/// </summary>
|
||||
public partial class AvatarGlyph : UserControl
|
||||
{
|
||||
public AvatarGlyph()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
<UserControl x:Class="Daybreak.Controls.ExperimentGlyph"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:Daybreak.Controls"
|
||||
mc:Ignorable="d"
|
||||
x:Name="_this"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<Viewbox>
|
||||
<Path Fill="{Binding ElementName=_this, Path=Foreground, Mode=OneWay}"
|
||||
Data="m23.8,22.5l-7.8,-12.6l0,-7.9l1,0c0.6,0 1,-0.4 1,-1s-0.4,-1 -1,-1l-3,0l0,9.9l3.5,6.1l-11,0l3.5,-6.1l0,-9.9l-3,0c-0.6,0 -1,0.4 -1,1s0.4,1 1,1l1,0l0,7.9l-7.8,12.7c-0.5,0.7 0,1.4 0.8,1.4l22,0c0.8,0 1.3,-0.5 0.8,-1.5zm-20.8,-0.5l2.9,-5l12.2,0l2.9,5l-18,0z"></Path>
|
||||
</Viewbox>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,28 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
using System.Windows.Navigation;
|
||||
using System.Windows.Shapes;
|
||||
|
||||
namespace Daybreak.Controls
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for ExperimentGlyph.xaml
|
||||
/// </summary>
|
||||
public partial class ExperimentGlyph : UserControl
|
||||
{
|
||||
public ExperimentGlyph()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
<UserControl x:Class="Daybreak.Controls.FileGlyph"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:Daybreak.Controls"
|
||||
mc:Ignorable="d"
|
||||
x:Name="_this"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<Viewbox>
|
||||
<Path Fill="{Binding ElementName=_this, Path=Foreground, Mode=OneWay}"
|
||||
Data="m52,0l-40,0c-6.627,0 -12,5.373 -12,12l0,72c0,6.627 5.373,12 12,12l55.875,0c6.627,0 12.125,-5.373 12.125,-12l0,-56c-4,-4 -22,-22 -28,-28zm0,11.178l16.709,16.822l-16.709,0l0,-16.822zm15.875,76.822l-55.875,0c-2.206,0 -4,-1.794 -4,-4l0,-72c0,-2.206 1.794,-4 4,-4l32,0l0,20l0,8l8,0l20,0l0,48c0,2.168 -1.889,4 -4.125,4z"></Path>
|
||||
</Viewbox>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,15 @@
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace Daybreak.Controls
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for FileGlyph.xaml
|
||||
/// </summary>
|
||||
public partial class FileGlyph : UserControl
|
||||
{
|
||||
public FileGlyph()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
<UserControl x:Class="Daybreak.Controls.FireballGlyph"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:Daybreak.Controls"
|
||||
mc:Ignorable="d"
|
||||
x:Name="_this"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<Viewbox>
|
||||
<Grid>
|
||||
<Line Stroke="{Binding ElementName=_this, Path=Foreground, Mode=OneWay}"
|
||||
X1="15" X2="26" Y1="11" Y2="0"></Line>
|
||||
<Ellipse Stroke="{Binding ElementName=_this, Path=Foreground, Mode=OneWay}"
|
||||
Width="4" Height="4"
|
||||
Margin="8,13,13,8"></Ellipse>
|
||||
<Path Stroke="{Binding ElementName=_this, Path=Foreground, Mode=OneWay}"
|
||||
Data="m15.025,0l-12.7,11.3c-3.1,3.1 -3.1,8.2 0,11.3s8.2,3.1 11.3,0l12.4,-11.6"></Path>
|
||||
</Grid>
|
||||
</Viewbox>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,28 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
using System.Windows.Navigation;
|
||||
using System.Windows.Shapes;
|
||||
|
||||
namespace Daybreak.Controls
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for FireballGlyph.xaml
|
||||
/// </summary>
|
||||
public partial class FireballGlyph : UserControl
|
||||
{
|
||||
public FireballGlyph()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
<UserControl x:Class="Daybreak.Controls.GoldenArrowGlyph"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:Daybreak.Controls"
|
||||
mc:Ignorable="d"
|
||||
x:Name="_this"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<Viewbox>
|
||||
<Grid>
|
||||
<Grid.RenderTransform>
|
||||
<RotateTransform Angle="180" CenterX="900" CenterY="595"></RotateTransform>
|
||||
</Grid.RenderTransform>
|
||||
<Path Fill="{Binding ElementName=_this, Path=Foreground, Mode=OneWay}"
|
||||
Data="m771.53119,1071.05017c-81,-64 -151,-120 -154,-126c-4,-5 -15,-7 -25,-3c-11,4 -77,12 -149,16c-146,10 -203,26 -326,92c-63,35 -82,41 -96,32c-22,-13 -28,-55 -14,-95c7,-20 7,-39 -1,-60c-8,-25 -7,-38 5,-65c9,-19 21,-34 27,-34c5,0 10,-15 10,-34c0,-49 32,-75 83,-67c4,0 7,-10 7,-24c0,-31 41,-75 70,-75c11,0 20,-6 20,-14c0,-41 73,-60 136,-36c23,9 30,7 50,-15c13,-14 27,-25 32,-25c5,0 14,-11 20,-25c6,-14 17,-25 23,-25c7,0 22,-10 34,-22c12,-13 38,-36 58,-53c34,-28 37,-34 38,-90l1,-60l149,-133c82,-74 154,-132 160,-130c6,2 73,62 149,133l138,130l1,60c1,56 4,62 38,90c20,17 46,40 58,53c12,12 27,22 34,22c6,0 17,11 23,25c6,14 15,25 20,25c5,0 19,11 32,25c20,22 27,24 50,15c63,-24 136,-5 136,36c0,8 8,14 19,14c32,0 71,39 71,71c0,16 3,28 8,28c50,-8 82,18 82,67c0,19 4,34 9,34c5,0 16,16 26,36c13,27 14,42 6,65c-7,20 -7,38 0,58c14,40 8,82 -14,95c-14,9 -33,3 -96,-32c-123,-66 -180,-82 -326,-92c-71,-4 -138,-11 -148,-15c-11,-5 -22,-2 -30,7c-7,9 -76,65 -154,126l-141,111l-149,-116zm277,-45c99,-78 119,-97 119,-120c1,-32 1,-32 78,-14c32,8 114,19 183,25c134,11 208,31 297,81c61,35 63,35 63,15c0,-8 -12,-22 -26,-31l-25,-17l25,-24c14,-13 26,-30 26,-38c0,-19 -27,-44 -56,-51c-24,-6 -24,-7 -9,-31c27,-40 13,-55 -44,-47l-50,6l11,-35c23,-76 -11,-87 -77,-26c-25,23 -48,39 -51,36c-3,-3 6,-27 20,-53c14,-27 26,-57 26,-68c0,-16 -6,-18 -41,-13c-22,3 -58,17 -80,31c-21,14 -41,26 -44,26c-3,0 -5,-20 -5,-45c0,-42 -2,-45 -19,-35c-32,16 -41,12 -41,-20c0,-36 -13,-38 -34,-8c-15,22 -16,21 -16,-27c0,-47 -1,-48 -17,-32c-17,17 -18,16 -28,-24c-6,-24 -17,-45 -24,-47c-11,-4 -12,5 -5,44c15,83 11,140 -11,164c-13,14 -18,33 -16,55c8,101 -156,220 -241,174c-14,-8 -23,-8 -31,0c-15,15 -61,14 -101,-3c-74,-31 -155,-132 -142,-179c3,-13 -2,-29 -13,-42c-26,-28 -32,-84 -17,-150c13,-52 8,-74 -13,-61c-5,4 -12,24 -16,47c-7,39 -8,40 -26,23c-18,-17 -19,-16 -19,32c0,47 -1,48 -16,26c-21,-30 -34,-28 -34,8c0,32 -9,36 -41,20c-17,-10 -19,-7 -19,35c0,25 -2,45 -5,45c-3,0 -23,-12 -44,-26c-22,-14 -58,-28 -80,-31c-35,-5 -41,-3 -41,13c0,11 12,41 26,68c14,26 23,50 20,53c-3,3 -26,-13 -51,-36c-66,-61 -100,-50 -77,26l11,35l-43,-6c-23,-4 -50,-4 -60,0c-15,6 -15,9 3,39l19,33l-26,7c-59,15 -69,55 -25,91c27,21 27,23 8,30c-24,9 -35,23 -35,46c0,14 10,11 57,-17c92,-53 173,-76 313,-87c69,-5 150,-15 181,-23c72,-19 69,-20 69,13c1,23 20,42 118,119c64,50 123,92 130,92c7,1 66,-41 132,-91zm-149,-229c7,-21 15,-39 19,-39c4,0 14,18 23,40c13,34 20,40 45,40c37,0 108,-52 135,-98l19,-32l-31,-31c-17,-17 -31,-32 -31,-34c0,-1 17,-6 37,-10c45,-8 53,-18 53,-66c0,-68 -45,-159 -78,-159c-9,1 -32,14 -51,30c-19,16 -36,28 -37,27c-2,-2 4,-27 13,-56c13,-47 13,-55 0,-68c-22,-23 -91,-34 -139,-24c-59,14 -69,31 -52,86c15,51 7,56 -33,25c-14,-11 -31,-20 -38,-20c-20,0 -52,43 -69,93c-29,88 -18,121 45,131l42,7l-34,35l-33,34l19,36c20,37 84,88 120,96c32,7 44,-2 56,-43zm-154,-439c11,0 23,-11 29,-28c32,-85 252,-85 292,1c7,15 21,27 31,27c10,0 30,9 45,21l26,20l0,-55l0,-56l-106,-102c-58,-57 -114,-108 -124,-115c-14,-10 -34,3 -143,100l-127,112l0,67l0,66l29,-29c16,-16 38,-29 48,-29z" />
|
||||
</Grid>
|
||||
</Viewbox>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,28 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
using System.Windows.Navigation;
|
||||
using System.Windows.Shapes;
|
||||
|
||||
namespace Daybreak.Controls
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for GoldenArrowGlyph.xaml
|
||||
/// </summary>
|
||||
public partial class GoldenArrowGlyph : UserControl
|
||||
{
|
||||
public GoldenArrowGlyph()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
<UserControl x:Class="Daybreak.Controls.AccountTemplate"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:Daybreak.Controls"
|
||||
x:Name="_this"
|
||||
mc:Ignorable="d"
|
||||
xmlns:converters="clr-namespace:Daybreak.Converters"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<UserControl.Resources>
|
||||
<ResourceDictionary>
|
||||
<converters:InverseBooleanConverter x:Key="InverseBooleanConverter"></converters:InverseBooleanConverter>
|
||||
</ResourceDictionary>
|
||||
</UserControl.Resources>
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*"></ColumnDefinition>
|
||||
<ColumnDefinition Width="auto"></ColumnDefinition>
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid HorizontalAlignment="Stretch">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="auto"></RowDefinition>
|
||||
<RowDefinition Height="auto"></RowDefinition>
|
||||
<RowDefinition Height="auto"></RowDefinition>
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="auto"></ColumnDefinition>
|
||||
<ColumnDefinition Width="*"></ColumnDefinition>
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock FontSize="16" Text="Username:" Foreground="White" Margin="5" Grid.Row="0" HorizontalAlignment="Right"></TextBlock>
|
||||
<TextBlock FontSize="16" Text="Password:" Foreground="White" Margin="5" Grid.Row="1" HorizontalAlignment="Right"></TextBlock>
|
||||
<TextBlock FontSize="16" Text="Character name:" Foreground="White" Margin="5" Grid.Row="2" HorizontalAlignment="Right"></TextBlock>
|
||||
<TextBox Text="{Binding ElementName=_this, Path=Username, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Foreground="White" Background="Transparent"
|
||||
BorderThickness="1" HorizontalAlignment="Stretch" Grid.Row="0" Grid.Column="1"
|
||||
FontSize="16" TextChanged="UsernameTextbox_TextChanged" Margin="5"></TextBox>
|
||||
<PasswordBox x:Name="PasswordBox" Foreground="White" Background="Transparent"
|
||||
BorderThickness="1" HorizontalAlignment="Stretch" Grid.Row="1" Grid.Column="1"
|
||||
FontSize="16" PasswordChanged="Passwordbox_PasswordChanged" Margin="5"></PasswordBox>
|
||||
<TextBox Text="{Binding ElementName=_this, Path=CharacterName, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Foreground="White" Background="Transparent"
|
||||
BorderThickness="1" HorizontalAlignment="Stretch" Grid.Row="2" Grid.Column="1"
|
||||
FontSize="16" TextChanged="CharacterNameTextbox_TextChanged" Margin="5"></TextBox>
|
||||
</Grid>
|
||||
<local:BinButton Grid.Column="2" Height="30" Width="30" Foreground="White" VerticalAlignment="Top" Margin="5, 15, 5, 5"
|
||||
Clicked="BinButton_Clicked"></local:BinButton>
|
||||
<local:StarGlyph Grid.Column="2" Height="30" Width="30" Foreground="White" VerticalAlignment="Top" Margin="5, 55, 5, 5"
|
||||
Clicked="StarGlyph_Clicked" IsEnabled="{Binding ElementName=_this, Path=IsDefault, Mode=OneWay, Converter={StaticResource InverseBooleanConverter}}"></local:StarGlyph>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,88 @@
|
||||
using Daybreak.Models;
|
||||
using System;
|
||||
using System.Extensions;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Extensions;
|
||||
|
||||
namespace Daybreak.Controls
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for AccountTemplate.xaml
|
||||
/// </summary>
|
||||
public partial class AccountTemplate : UserControl
|
||||
{
|
||||
public static readonly DependencyProperty UsernameProperty = DependencyPropertyExtensions.Register<AccountTemplate, string>(nameof(Username));
|
||||
public static readonly DependencyProperty CharacterNameProperty = DependencyPropertyExtensions.Register<AccountTemplate, string>(nameof(CharacterName));
|
||||
public static readonly DependencyProperty PasswordProperty = DependencyPropertyExtensions.Register<AccountTemplate, string>(nameof(Password));
|
||||
public static readonly DependencyProperty IsDefaultProperty = DependencyPropertyExtensions.Register<AccountTemplate, bool>(nameof(IsDefault));
|
||||
|
||||
|
||||
public event EventHandler RemoveClicked;
|
||||
public event EventHandler DefaultClicked;
|
||||
|
||||
public string Username
|
||||
{
|
||||
get => this.GetTypedValue<string>(UsernameProperty);
|
||||
set => this.SetValue(UsernameProperty, value);
|
||||
}
|
||||
public string Password
|
||||
{
|
||||
get => this.GetTypedValue<string>(PasswordProperty);
|
||||
set => this.SetValue(PasswordProperty, value);
|
||||
}
|
||||
public string CharacterName
|
||||
{
|
||||
get => this.GetTypedValue<string>(CharacterNameProperty);
|
||||
set => this.SetValue(CharacterNameProperty, value);
|
||||
}
|
||||
public bool IsDefault
|
||||
{
|
||||
get => this.GetTypedValue<bool>(IsDefaultProperty);
|
||||
set => this.SetValue(IsDefaultProperty, value);
|
||||
}
|
||||
|
||||
public AccountTemplate()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
this.DataContextChanged += AccountTemplate_DataContextChanged;
|
||||
}
|
||||
|
||||
private void AccountTemplate_DataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
if (e.NewValue is LoginCredentials loginCredentials)
|
||||
{
|
||||
this.PasswordBox.Password = loginCredentials.Password;
|
||||
this.Username = loginCredentials.Username;
|
||||
this.CharacterName = loginCredentials.CharacterName;
|
||||
this.IsDefault = loginCredentials.Default;
|
||||
}
|
||||
}
|
||||
|
||||
private void BinButton_Clicked(object sender, EventArgs e)
|
||||
{
|
||||
this.RemoveClicked?.Invoke(this, e);
|
||||
}
|
||||
|
||||
private void UsernameTextbox_TextChanged(object sender, EventArgs e)
|
||||
{
|
||||
this.DataContext.As<LoginCredentials>().Username = this.Username;
|
||||
}
|
||||
|
||||
private void CharacterNameTextbox_TextChanged(object sender, EventArgs e)
|
||||
{
|
||||
this.DataContext.As<LoginCredentials>().CharacterName = this.CharacterName;
|
||||
}
|
||||
|
||||
private void Passwordbox_PasswordChanged(object sender, EventArgs e)
|
||||
{
|
||||
this.Password = sender.As<PasswordBox>()?.Password;
|
||||
this.DataContext.As<LoginCredentials>().Password = this.Password;
|
||||
}
|
||||
|
||||
private void StarGlyph_Clicked(object sender, EventArgs e)
|
||||
{
|
||||
this.DefaultClicked?.Invoke(this, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
<UserControl x:Class="Daybreak.Controls.AttributeTemplate"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:Daybreak.Controls"
|
||||
mc:Ignorable="d"
|
||||
x:Name="_this"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<Grid>
|
||||
<WrapPanel Orientation="Horizontal" HorizontalAlignment="Left" Margin="10, 0, 10, 0">
|
||||
<local:HelpButton Width="20" Height="20" Margin="3, 0, 3, 0" Foreground="White"
|
||||
Clicked="HelpButton_Clicked" Cursor="Hand"></local:HelpButton>
|
||||
<TextBlock Text="{Binding Attribute.Name}" FontSize="16" Foreground="White"></TextBlock>
|
||||
</WrapPanel>
|
||||
<WrapPanel Orientation="Horizontal" HorizontalAlignment="Right" Margin="10, 0, 10, 0">
|
||||
<local:MinusButton Foreground="White" Height="20" Clicked="MinusButton_Clicked" Cursor="Hand"
|
||||
IsEnabled="{Binding ElementName=_this, Path=CanSubtract, Mode=OneWay}"></local:MinusButton>
|
||||
<TextBox Background="Transparent" Foreground="White" FontSize="16" IsReadOnly="True" Width="30"
|
||||
Text="{Binding Points}"></TextBox>
|
||||
<local:AddButton Foreground="White" Height="20" Clicked="AddButton_Clicked" Cursor="Hand"
|
||||
IsEnabled="{Binding ElementName=_this, Path=CanAdd, Mode=OneWay}"></local:AddButton>
|
||||
</WrapPanel>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,84 @@
|
||||
using Daybreak.Models.Builds;
|
||||
using System;
|
||||
using System.Extensions;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Extensions;
|
||||
|
||||
namespace Daybreak.Controls
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for AttributeTemplate.xaml
|
||||
/// </summary>
|
||||
public partial class AttributeTemplate : UserControl
|
||||
{
|
||||
public readonly static DependencyProperty CanAddProperty =
|
||||
DependencyPropertyExtensions.Register<AttributeTemplate, bool>(nameof(CanAdd), new PropertyMetadata(false));
|
||||
public readonly static DependencyProperty CanSubtractProperty =
|
||||
DependencyPropertyExtensions.Register<AttributeTemplate, bool>(nameof(CanSubtract), new PropertyMetadata(false));
|
||||
|
||||
public event EventHandler<AttributeEntry> HelpClicked;
|
||||
|
||||
public bool CanAdd
|
||||
{
|
||||
get => this.GetTypedValue<bool>(CanAddProperty);
|
||||
private set => this.SetValue(CanAddProperty, value);
|
||||
}
|
||||
|
||||
public bool CanSubtract
|
||||
{
|
||||
get => this.GetTypedValue<bool>(CanSubtractProperty);
|
||||
private set => this.SetValue(CanSubtractProperty, value);
|
||||
}
|
||||
|
||||
public AttributeTemplate()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
this.DataContextChanged += AttributeTemplate_DataContextChanged;
|
||||
}
|
||||
|
||||
private void AttributeTemplate_DataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
if (e.NewValue is AttributeEntry attributeEntry)
|
||||
{
|
||||
if (attributeEntry.Points > 0)
|
||||
{
|
||||
this.CanSubtract = true;
|
||||
}
|
||||
|
||||
if (attributeEntry.Points < 12)
|
||||
{
|
||||
this.CanAdd = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void MinusButton_Clicked(object sender, System.EventArgs e)
|
||||
{
|
||||
if (this.DataContext.As<AttributeEntry>().Points > 0)
|
||||
{
|
||||
this.DataContext.As<AttributeEntry>().Points--;
|
||||
this.CanSubtract = this.DataContext.As<AttributeEntry>().Points > 0;
|
||||
this.CanAdd = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void AddButton_Clicked(object sender, System.EventArgs e)
|
||||
{
|
||||
if (this.DataContext.As<AttributeEntry>().Points < 12)
|
||||
{
|
||||
this.DataContext.As<AttributeEntry>().Points++;
|
||||
this.CanAdd = this.DataContext.As<AttributeEntry>().Points < 12;
|
||||
this.CanSubtract = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void HelpButton_Clicked(object sender, System.EventArgs e)
|
||||
{
|
||||
if (this.DataContext is AttributeEntry attributeEntry)
|
||||
{
|
||||
this.HelpClicked?.Invoke(this, attributeEntry);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
<UserControl x:Class="Daybreak.Controls.BuildEntryTemplate"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:Daybreak.Controls"
|
||||
mc:Ignorable="d"
|
||||
xmlns:controls="clr-namespace:Daybreak.Controls"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<Grid>
|
||||
<TextBlock FontSize="16" Foreground="White" Text="{Binding Name}" HorizontalAlignment="Center" VerticalAlignment="Center"></TextBlock>
|
||||
<controls:BinButton Width="30" Height="30" Foreground="White" HorizontalAlignment="Right" Clicked="BinButton_Clicked"></controls:BinButton>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,27 @@
|
||||
using Daybreak.Models.Builds;
|
||||
using System;
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace Daybreak.Controls
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for BuildEntryTemplate.xaml
|
||||
/// </summary>
|
||||
public partial class BuildEntryTemplate : UserControl
|
||||
{
|
||||
public event EventHandler<BuildEntry> RemoveClicked;
|
||||
|
||||
public BuildEntryTemplate()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void BinButton_Clicked(object sender, EventArgs e)
|
||||
{
|
||||
if (this.DataContext is BuildEntry buildEntry)
|
||||
{
|
||||
this.RemoveClicked?.Invoke(this, buildEntry);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,169 @@
|
||||
<UserControl x:Class="Daybreak.Controls.BuildTemplate"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:Daybreak.Controls"
|
||||
xmlns:interactivity="http://schemas.microsoft.com/expression/2010/interactivity"
|
||||
xmlns:behaviors="clr-namespace:Daybreak.Behaviors"
|
||||
xmlns:converters="clr-namespace:Daybreak.Converters"
|
||||
mc:Ignorable="d"
|
||||
x:Name="_this"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<Grid Background="Transparent" MouseLeftButtonDown="Grid_MouseLeftButtonDown">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="auto"></RowDefinition>
|
||||
<RowDefinition Height="auto"></RowDefinition>
|
||||
<RowDefinition Height="auto"></RowDefinition>
|
||||
<RowDefinition Height="*"></RowDefinition>
|
||||
<RowDefinition Height="auto"></RowDefinition>
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*"></ColumnDefinition>
|
||||
<ColumnDefinition Width="auto"></ColumnDefinition>
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid Grid.Row="1">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="auto"></ColumnDefinition>
|
||||
<ColumnDefinition Width="auto"></ColumnDefinition>
|
||||
<ColumnDefinition Width="*"></ColumnDefinition>
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock Text="Primary Profession: " FontSize="16" Foreground="White" Grid.Column="1"></TextBlock>
|
||||
<ListView FontSize="16" Foreground="White" Grid.Column="2" BorderThickness="0"
|
||||
Background="Transparent" ItemsSource="{Binding ElementName=_this, Path=Professions, Mode=OneWay}"
|
||||
SelectedItem="{Binding ElementName=_this, Path=PrimaryProfession, Mode=TwoWay}" Height="30"
|
||||
SelectionMode="Single" ScrollViewer.VerticalScrollBarVisibility="Disabled"
|
||||
PreviewMouseWheel="ListView_NavigateWithMouseWheel">
|
||||
<ListView.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<TextBlock Text="{Binding Name, Mode=OneWay}"></TextBlock>
|
||||
</DataTemplate>
|
||||
</ListView.ItemTemplate>
|
||||
<interactivity:Interaction.Behaviors>
|
||||
<behaviors:ScrollIntoView></behaviors:ScrollIntoView>
|
||||
</interactivity:Interaction.Behaviors>
|
||||
</ListView>
|
||||
<local:HelpButton Grid.Column="0" Foreground="White" Width="20" Height="20" Margin="3"
|
||||
Clicked="HelpButtonPrimary_Clicked" Cursor="Hand"></local:HelpButton>
|
||||
</Grid>
|
||||
<Grid Grid.Row="2">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="auto"></ColumnDefinition>
|
||||
<ColumnDefinition Width="auto"></ColumnDefinition>
|
||||
<ColumnDefinition Width="*"></ColumnDefinition>
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock Text="Secondary Profession: " FontSize="16" Foreground="White" Grid.Column="1"></TextBlock>
|
||||
<ListView FontSize="16" Foreground="White" Grid.Column="2" BorderThickness="0"
|
||||
Background="Transparent" ItemsSource="{Binding ElementName=_this, Path=Professions, Mode=OneWay}"
|
||||
SelectedItem="{Binding ElementName=_this, Path=SecondaryProfession, Mode=TwoWay}" Height="30"
|
||||
SelectionMode="Single" ScrollViewer.VerticalScrollBarVisibility="Disabled"
|
||||
PreviewMouseWheel="ListView_NavigateWithMouseWheel">
|
||||
<ListView.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<TextBlock Text="{Binding Name, Mode=OneWay}"></TextBlock>
|
||||
</DataTemplate>
|
||||
</ListView.ItemTemplate>
|
||||
<interactivity:Interaction.Behaviors>
|
||||
<behaviors:ScrollIntoView></behaviors:ScrollIntoView>
|
||||
</interactivity:Interaction.Behaviors>
|
||||
</ListView>
|
||||
<local:HelpButton Grid.Column="0" Foreground="White" Width="20" Height="20" Margin="3"
|
||||
Clicked="HelpButtonSecondary_Clicked" Cursor="Hand"></local:HelpButton>
|
||||
</Grid>
|
||||
<Grid Grid.Row="3">
|
||||
<ListBox Background="Transparent" ItemsSource="{Binding ElementName=_this, Path=Attributes, Mode=OneWay}"
|
||||
HorizontalContentAlignment="Stretch" BorderThickness="0">
|
||||
<ListBox.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<local:AttributeTemplate HelpClicked="AttributeTemplate_HelpClicked"></local:AttributeTemplate>
|
||||
</DataTemplate>
|
||||
</ListBox.ItemTemplate>
|
||||
</ListBox>
|
||||
</Grid>
|
||||
<Grid Grid.Row="4">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*"></ColumnDefinition>
|
||||
<ColumnDefinition Width="*"></ColumnDefinition>
|
||||
<ColumnDefinition Width="*"></ColumnDefinition>
|
||||
<ColumnDefinition Width="*"></ColumnDefinition>
|
||||
<ColumnDefinition Width="*"></ColumnDefinition>
|
||||
<ColumnDefinition Width="*"></ColumnDefinition>
|
||||
<ColumnDefinition Width="*"></ColumnDefinition>
|
||||
<ColumnDefinition Width="*"></ColumnDefinition>
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="*"></RowDefinition>
|
||||
<RowDefinition Height="auto"></RowDefinition>
|
||||
</Grid.RowDefinitions>
|
||||
<local:SkillTemplate Grid.Column="0"
|
||||
Foreground="White" Cursor="Hand"
|
||||
FontSize="22" DataContext="{Binding ElementName=_this, Path=Skill0, Mode=TwoWay}"
|
||||
VerticalAlignment="Stretch" Clicked="SkillTemplate_Clicked"
|
||||
RemoveClicked="SkillTemplate_RemoveClicked"></local:SkillTemplate>
|
||||
<local:SkillTemplate Grid.Column="1"
|
||||
Foreground="White" Cursor="Hand"
|
||||
FontSize="22" DataContext="{Binding ElementName=_this, Path=Skill1, Mode=TwoWay}"
|
||||
VerticalAlignment="Stretch" Clicked="SkillTemplate_Clicked"
|
||||
RemoveClicked="SkillTemplate_RemoveClicked"></local:SkillTemplate>
|
||||
<local:SkillTemplate Grid.Column="2"
|
||||
Foreground="White" Cursor="Hand"
|
||||
FontSize="22" DataContext="{Binding ElementName=_this, Path=Skill2, Mode=TwoWay}"
|
||||
VerticalAlignment="Stretch" Clicked="SkillTemplate_Clicked"
|
||||
RemoveClicked="SkillTemplate_RemoveClicked"></local:SkillTemplate>
|
||||
<local:SkillTemplate Grid.Column="3"
|
||||
Foreground="White" Cursor="Hand"
|
||||
FontSize="22" DataContext="{Binding ElementName=_this, Path=Skill3, Mode=TwoWay}"
|
||||
VerticalAlignment="Stretch" Clicked="SkillTemplate_Clicked"
|
||||
RemoveClicked="SkillTemplate_RemoveClicked"></local:SkillTemplate>
|
||||
<local:SkillTemplate Grid.Column="4"
|
||||
Foreground="White" Cursor="Hand"
|
||||
FontSize="22" DataContext="{Binding ElementName=_this, Path=Skill4, Mode=TwoWay}"
|
||||
VerticalAlignment="Stretch" Clicked="SkillTemplate_Clicked"
|
||||
RemoveClicked="SkillTemplate_RemoveClicked"></local:SkillTemplate>
|
||||
<local:SkillTemplate Grid.Column="5"
|
||||
Foreground="White" Cursor="Hand"
|
||||
FontSize="22" DataContext="{Binding ElementName=_this, Path=Skill5, Mode=TwoWay}"
|
||||
VerticalAlignment="Stretch" Clicked="SkillTemplate_Clicked"
|
||||
RemoveClicked="SkillTemplate_RemoveClicked"></local:SkillTemplate>
|
||||
<local:SkillTemplate Grid.Column="6"
|
||||
Foreground="White" Cursor="Hand"
|
||||
FontSize="22" DataContext="{Binding ElementName=_this, Path=Skill6, Mode=TwoWay}"
|
||||
VerticalAlignment="Stretch" Clicked="SkillTemplate_Clicked"
|
||||
RemoveClicked="SkillTemplate_RemoveClicked"></local:SkillTemplate>
|
||||
<local:SkillTemplate Grid.Column="7"
|
||||
Foreground="White" Cursor="Hand"
|
||||
FontSize="22" DataContext="{Binding ElementName=_this, Path=Skill7, Mode=TwoWay}"
|
||||
VerticalAlignment="Stretch" Clicked="SkillTemplate_Clicked"
|
||||
RemoveClicked="SkillTemplate_RemoveClicked"></local:SkillTemplate>
|
||||
<TextBlock Grid.Column="0" Grid.Row="1" TextWrapping="Wrap" FontSize="16"
|
||||
Foreground="White" Text="{Binding ElementName=_this, Path=Skill0.Name, Mode=OneWay}"></TextBlock>
|
||||
<TextBlock Grid.Column="1" Grid.Row="1" TextWrapping="Wrap" FontSize="16"
|
||||
Foreground="White" Text="{Binding ElementName=_this, Path=Skill1.Name, Mode=OneWay}"></TextBlock>
|
||||
<TextBlock Grid.Column="2" Grid.Row="1" TextWrapping="Wrap" FontSize="16"
|
||||
Foreground="White" Text="{Binding ElementName=_this, Path=Skill2.Name, Mode=OneWay}"></TextBlock>
|
||||
<TextBlock Grid.Column="3" Grid.Row="1" TextWrapping="Wrap" FontSize="16"
|
||||
Foreground="White" Text="{Binding ElementName=_this, Path=Skill3.Name, Mode=OneWay}"></TextBlock>
|
||||
<TextBlock Grid.Column="4" Grid.Row="1" TextWrapping="Wrap" FontSize="16"
|
||||
Foreground="White" Text="{Binding ElementName=_this, Path=Skill4.Name, Mode=OneWay}"></TextBlock>
|
||||
<TextBlock Grid.Column="5" Grid.Row="1" TextWrapping="Wrap" FontSize="16"
|
||||
Foreground="White" Text="{Binding ElementName=_this, Path=Skill5.Name, Mode=OneWay}"></TextBlock>
|
||||
<TextBlock Grid.Column="6" Grid.Row="1" TextWrapping="Wrap" FontSize="16"
|
||||
Foreground="White" Text="{Binding ElementName=_this, Path=Skill6.Name, Mode=OneWay}"></TextBlock>
|
||||
<TextBlock Grid.Column="7" Grid.Row="1" TextWrapping="Wrap" FontSize="16"
|
||||
Foreground="White" Text="{Binding ElementName=_this, Path=Skill7.Name, Mode=OneWay}"></TextBlock>
|
||||
</Grid>
|
||||
<Grid Grid.Column="1" Grid.RowSpan="6">
|
||||
<local:ChromiumBrowserWrapper x:Name="SkillBrowser" ControlsEnabled="False" Width="0" AddressBarReadonly="True" CanNavigate="True"></local:ChromiumBrowserWrapper>
|
||||
</Grid>
|
||||
<Grid Grid.Column="1" Grid.RowSpan="6">
|
||||
<ListView x:Name="SkillsListView" Background="Transparent" Width="0"
|
||||
ItemsSource="{Binding ElementName=_this, Path=AvailableSkills, Mode=OneWay}" MouseDoubleClick="ListView_MouseDoubleClick">
|
||||
<ListView.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<TextBlock FontSize="16" Foreground="White" TextWrapping="Wrap" Text="{Binding Name}"></TextBlock>
|
||||
</DataTemplate>
|
||||
</ListView.ItemTemplate>
|
||||
</ListView>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,367 @@
|
||||
using Daybreak.Launch;
|
||||
using Daybreak.Models.Builds;
|
||||
using Daybreak.Services.IconRetrieve;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Extensions;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Extensions;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
|
||||
namespace Daybreak.Controls
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for BuildTemplate.xaml
|
||||
/// </summary>
|
||||
public partial class BuildTemplate : UserControl
|
||||
{
|
||||
private const string InfoNamePlaceholder = "[NAME]";
|
||||
private const string BaseAddress = $"https://wiki.guildwars.com/wiki/{InfoNamePlaceholder}";
|
||||
|
||||
public readonly static DependencyProperty PrimaryProfessionProperty =
|
||||
DependencyPropertyExtensions.Register<BuildTemplate, Profession>(nameof(PrimaryProfession), new PropertyMetadata(Profession.None));
|
||||
public readonly static DependencyProperty SecondaryProfessionProperty =
|
||||
DependencyPropertyExtensions.Register<BuildTemplate, Profession>(nameof(SecondaryProfession), new PropertyMetadata(Profession.None));
|
||||
public readonly static DependencyProperty Skill0Property =
|
||||
DependencyPropertyExtensions.Register<BuildTemplate, Skill>(nameof(Skill0), new PropertyMetadata(Skill.NoSkill));
|
||||
public readonly static DependencyProperty Skill1Property =
|
||||
DependencyPropertyExtensions.Register<BuildTemplate, Skill>(nameof(Skill1), new PropertyMetadata(Skill.NoSkill));
|
||||
public readonly static DependencyProperty Skill2Property =
|
||||
DependencyPropertyExtensions.Register<BuildTemplate, Skill>(nameof(Skill2), new PropertyMetadata(Skill.NoSkill));
|
||||
public readonly static DependencyProperty Skill3Property =
|
||||
DependencyPropertyExtensions.Register<BuildTemplate, Skill>(nameof(Skill3), new PropertyMetadata(Skill.NoSkill));
|
||||
public readonly static DependencyProperty Skill4Property =
|
||||
DependencyPropertyExtensions.Register<BuildTemplate, Skill>(nameof(Skill4), new PropertyMetadata(Skill.NoSkill));
|
||||
public readonly static DependencyProperty Skill5Property =
|
||||
DependencyPropertyExtensions.Register<BuildTemplate, Skill>(nameof(Skill5), new PropertyMetadata(Skill.NoSkill));
|
||||
public readonly static DependencyProperty Skill6Property =
|
||||
DependencyPropertyExtensions.Register<BuildTemplate, Skill>(nameof(Skill6), new PropertyMetadata(Skill.NoSkill));
|
||||
public readonly static DependencyProperty Skill7Property =
|
||||
DependencyPropertyExtensions.Register<BuildTemplate, Skill>(nameof(Skill7), new PropertyMetadata(Skill.NoSkill));
|
||||
|
||||
private BuildEntry loadedBuild;
|
||||
private SkillTemplate selectingSkillTemplate;
|
||||
|
||||
public Profession PrimaryProfession
|
||||
{
|
||||
get => this.GetTypedValue<Profession>(PrimaryProfessionProperty);
|
||||
set => this.SetValue(PrimaryProfessionProperty, value);
|
||||
}
|
||||
public Profession SecondaryProfession
|
||||
{
|
||||
get => this.GetTypedValue<Profession>(SecondaryProfessionProperty);
|
||||
set => this.SetValue(SecondaryProfessionProperty, value);
|
||||
}
|
||||
public Skill Skill0
|
||||
{
|
||||
get => this.GetTypedValue<Skill>(Skill0Property);
|
||||
set => this.SetValue(Skill0Property, value);
|
||||
}
|
||||
public Skill Skill1
|
||||
{
|
||||
get => this.GetTypedValue<Skill>(Skill1Property);
|
||||
set => this.SetValue(Skill1Property, value);
|
||||
}
|
||||
public Skill Skill2
|
||||
{
|
||||
get => this.GetTypedValue<Skill>(Skill2Property);
|
||||
set => this.SetValue(Skill2Property, value);
|
||||
}
|
||||
public Skill Skill3
|
||||
{
|
||||
get => this.GetTypedValue<Skill>(Skill3Property);
|
||||
set => this.SetValue(Skill3Property, value);
|
||||
}
|
||||
public Skill Skill4
|
||||
{
|
||||
get => this.GetTypedValue<Skill>(Skill4Property);
|
||||
set => this.SetValue(Skill4Property, value);
|
||||
}
|
||||
public Skill Skill5
|
||||
{
|
||||
get => this.GetTypedValue<Skill>(Skill5Property);
|
||||
set => this.SetValue(Skill5Property, value);
|
||||
}
|
||||
public Skill Skill6
|
||||
{
|
||||
get => this.GetTypedValue<Skill>(Skill6Property);
|
||||
set => this.SetValue(Skill6Property, value);
|
||||
}
|
||||
public Skill Skill7
|
||||
{
|
||||
get => this.GetTypedValue<Skill>(Skill7Property);
|
||||
set => this.SetValue(Skill7Property, value);
|
||||
}
|
||||
public ObservableCollection<Skill> AvailableSkills { get; } = new ObservableCollection<Skill>();
|
||||
public ObservableCollection<AttributeEntry> Attributes { get; } = new ObservableCollection<AttributeEntry>();
|
||||
public ObservableCollection<Profession> Professions { get; } = new ObservableCollection<Profession>(Profession.Professions);
|
||||
|
||||
public BuildTemplate()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
this.DataContextChanged += BuildTemplate_DataContextChanged;
|
||||
}
|
||||
|
||||
protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
base.OnPropertyChanged(e);
|
||||
if (e.Property == PrimaryProfessionProperty || e.Property == SecondaryProfessionProperty)
|
||||
{
|
||||
if (e.Property == PrimaryProfessionProperty)
|
||||
{
|
||||
this.loadedBuild.Build.Primary = this.PrimaryProfession;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.loadedBuild.Build.Secondary = this.SecondaryProfession;
|
||||
}
|
||||
this.LoadSkills();
|
||||
this.LoadAttributes();
|
||||
}
|
||||
}
|
||||
|
||||
private void BuildTemplate_DataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
if(e.NewValue is BuildEntry)
|
||||
{
|
||||
this.LoadBuild();
|
||||
this.LoadSkills();
|
||||
this.LoadAttributes();
|
||||
}
|
||||
}
|
||||
|
||||
private void Grid_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
|
||||
{
|
||||
this.HideSkillListView();
|
||||
this.HideInfoBrowser();
|
||||
}
|
||||
|
||||
private void LoadAttributes()
|
||||
{
|
||||
var possibleAttributes = new List<AttributeEntry>();
|
||||
if (this.PrimaryProfession != Profession.None)
|
||||
{
|
||||
possibleAttributes.Add(new AttributeEntry { Attribute = this.PrimaryProfession.PrimaryAttribute });
|
||||
possibleAttributes.AddRange(this.PrimaryProfession.Attributes.Select(a => new AttributeEntry { Attribute = a }));
|
||||
}
|
||||
|
||||
if (this.SecondaryProfession != Profession.None && this.SecondaryProfession != this.PrimaryProfession)
|
||||
{
|
||||
possibleAttributes.AddRange(this.SecondaryProfession.Attributes.Select(a => new AttributeEntry { Attribute = a }));
|
||||
}
|
||||
|
||||
this.Attributes.ClearAnd().AddRange(possibleAttributes.Select(entry =>
|
||||
{
|
||||
var maybePresentAttribute = this.loadedBuild.Build.Attributes.Where(buildEntry => entry.Attribute == buildEntry.Attribute).FirstOrDefault();
|
||||
if (maybePresentAttribute is null)
|
||||
{
|
||||
return entry;
|
||||
}
|
||||
|
||||
entry.Points = maybePresentAttribute.Points;
|
||||
return entry;
|
||||
}));
|
||||
|
||||
this.loadedBuild.Build.Attributes = this.Attributes.ToList();
|
||||
}
|
||||
|
||||
private void LoadSkills()
|
||||
{
|
||||
var possibleSkills = Skill.Skills
|
||||
.Where(s => s.Profession == PrimaryProfession || s.Profession == SecondaryProfession || s.Profession == Profession.None)
|
||||
.Where(s => s != Skill.NoSkill)
|
||||
.OrderBy(s => s.Name);
|
||||
this.AvailableSkills.ClearAnd().AddRange(possibleSkills);
|
||||
|
||||
if (this.Skill0.Profession != PrimaryProfession &&
|
||||
this.Skill0.Profession != SecondaryProfession &&
|
||||
this.Skill0.Profession != Profession.None)
|
||||
{
|
||||
this.Skill0 = Skill.NoSkill;
|
||||
}
|
||||
if (this.Skill1.Profession != PrimaryProfession &&
|
||||
this.Skill1.Profession != SecondaryProfession &&
|
||||
this.Skill1.Profession != Profession.None)
|
||||
{
|
||||
this.Skill1 = Skill.NoSkill;
|
||||
}
|
||||
if (this.Skill2.Profession != PrimaryProfession &&
|
||||
this.Skill2.Profession != SecondaryProfession &&
|
||||
this.Skill2.Profession != Profession.None)
|
||||
{
|
||||
this.Skill2 = Skill.NoSkill;
|
||||
}
|
||||
if (this.Skill3.Profession != PrimaryProfession &&
|
||||
this.Skill3.Profession != SecondaryProfession &&
|
||||
this.Skill3.Profession != Profession.None)
|
||||
{
|
||||
this.Skill3 = Skill.NoSkill;
|
||||
}
|
||||
if (this.Skill4.Profession != PrimaryProfession &&
|
||||
this.Skill4.Profession != SecondaryProfession &&
|
||||
this.Skill4.Profession != Profession.None)
|
||||
{
|
||||
this.Skill4 = Skill.NoSkill;
|
||||
}
|
||||
if (this.Skill5.Profession != PrimaryProfession &&
|
||||
this.Skill5.Profession != SecondaryProfession &&
|
||||
this.Skill5.Profession != Profession.None)
|
||||
{
|
||||
this.Skill5 = Skill.NoSkill;
|
||||
}
|
||||
if (this.Skill6.Profession != PrimaryProfession &&
|
||||
this.Skill6.Profession != SecondaryProfession &&
|
||||
this.Skill6.Profession != Profession.None)
|
||||
{
|
||||
this.Skill6 = Skill.NoSkill;
|
||||
}
|
||||
if (this.Skill7.Profession != PrimaryProfession &&
|
||||
this.Skill7.Profession != SecondaryProfession &&
|
||||
this.Skill7.Profession != Profession.None)
|
||||
{
|
||||
this.Skill7 = Skill.NoSkill;
|
||||
}
|
||||
}
|
||||
|
||||
private void LoadBuild()
|
||||
{
|
||||
var build = this.DataContext.As<BuildEntry>();
|
||||
this.loadedBuild = build;
|
||||
this.PrimaryProfession = build.Build.Primary;
|
||||
this.SecondaryProfession = build.Build.Secondary;
|
||||
this.Skill0 = build.Build.Skills[0];
|
||||
this.Skill1 = build.Build.Skills[1];
|
||||
this.Skill2 = build.Build.Skills[2];
|
||||
this.Skill3 = build.Build.Skills[3];
|
||||
this.Skill4 = build.Build.Skills[4];
|
||||
this.Skill5 = build.Build.Skills[5];
|
||||
this.Skill6 = build.Build.Skills[6];
|
||||
this.Skill7 = build.Build.Skills[7];
|
||||
}
|
||||
|
||||
private void BrowseToInfo(string infoName)
|
||||
{
|
||||
var address = BaseAddress.Replace(InfoNamePlaceholder, infoName.Replace(" ", "_"));
|
||||
this.SkillBrowser.Address = address;
|
||||
this.ShowInfoBrowser();
|
||||
}
|
||||
|
||||
private void ShowInfoBrowser()
|
||||
{
|
||||
this.SkillBrowser.Width = 400;
|
||||
this.SkillsListView.Width = 0;
|
||||
}
|
||||
|
||||
private void HideInfoBrowser()
|
||||
{
|
||||
this.SkillBrowser.Width = 0;
|
||||
}
|
||||
|
||||
private void ShowSkillListView()
|
||||
{
|
||||
this.SkillBrowser.Width = 0;
|
||||
this.SkillsListView.Width = 400;
|
||||
}
|
||||
|
||||
private void HideSkillListView()
|
||||
{
|
||||
this.SkillsListView.Width = 0;
|
||||
}
|
||||
|
||||
private void HelpButtonPrimary_Clicked(object sender, System.EventArgs e)
|
||||
{
|
||||
if (this.PrimaryProfession == Profession.None)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
this.BrowseToInfo(PrimaryProfession.Name);
|
||||
if (e is RoutedEventArgs routedEventArgs)
|
||||
{
|
||||
routedEventArgs.Handled = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void HelpButtonSecondary_Clicked(object sender, System.EventArgs e)
|
||||
{
|
||||
if (this.SecondaryProfession == Profession.None)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
this.BrowseToInfo(this.SecondaryProfession.Name);
|
||||
if (e is RoutedEventArgs routedEventArgs)
|
||||
{
|
||||
routedEventArgs.Handled = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void AttributeTemplate_HelpClicked(object sender, AttributeEntry e)
|
||||
{
|
||||
this.BrowseToInfo(e.Attribute.Name);
|
||||
}
|
||||
|
||||
private void SkillTemplate_Clicked(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var skill = sender.As<SkillTemplate>().DataContext.As<Skill>();
|
||||
if (skill == Skill.NoSkill)
|
||||
{
|
||||
this.ShowSkillListView();
|
||||
this.selectingSkillTemplate = sender.As<SkillTemplate>();
|
||||
}
|
||||
else
|
||||
{
|
||||
this.BrowseToInfo(skill.Name);
|
||||
}
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
private void SkillTemplate_RemoveClicked(object sender, System.EventArgs e)
|
||||
{
|
||||
sender.As<SkillTemplate>().DataContext = Skill.NoSkill;
|
||||
}
|
||||
|
||||
private void ListView_MouseDoubleClick(object sender, System.Windows.Input.MouseButtonEventArgs e)
|
||||
{
|
||||
if (this.selectingSkillTemplate is null)
|
||||
{
|
||||
this.HideSkillListView();
|
||||
return;
|
||||
}
|
||||
|
||||
this.selectingSkillTemplate.DataContext = sender.As<ListView>().SelectedItem;
|
||||
this.HideSkillListView();
|
||||
this.loadedBuild.Build.Skills[0] = Skill0;
|
||||
this.loadedBuild.Build.Skills[1] = Skill1;
|
||||
this.loadedBuild.Build.Skills[2] = Skill2;
|
||||
this.loadedBuild.Build.Skills[3] = Skill3;
|
||||
this.loadedBuild.Build.Skills[4] = Skill4;
|
||||
this.loadedBuild.Build.Skills[5] = Skill5;
|
||||
this.loadedBuild.Build.Skills[6] = Skill6;
|
||||
this.loadedBuild.Build.Skills[7] = Skill7;
|
||||
}
|
||||
|
||||
private void ListView_NavigateWithMouseWheel(object sender, System.Windows.Input.MouseWheelEventArgs e)
|
||||
{
|
||||
e.Handled = true;
|
||||
if (e.Delta > 0)
|
||||
{
|
||||
sender.As<ListView>().SelectedIndex = sender.As<ListView>().SelectedIndex > 0 ?
|
||||
sender.As<ListView>().SelectedIndex - 1 :
|
||||
0;
|
||||
}
|
||||
else
|
||||
{
|
||||
sender.As<ListView>().SelectedIndex = sender.As<ListView>().SelectedIndex < sender.As<ListView>().Items.Count - 1 ?
|
||||
sender.As<ListView>().SelectedIndex + 1 :
|
||||
sender.As<ListView>().Items.Count;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
<UserControl x:Class="Daybreak.Controls.GuildwarsPathTemplate"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:converters="clr-namespace:Daybreak.Converters"
|
||||
xmlns:local="clr-namespace:Daybreak.Controls"
|
||||
mc:Ignorable="d"
|
||||
x:Name="_this"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<UserControl.Resources>
|
||||
<ResourceDictionary>
|
||||
<converters:InverseBooleanConverter x:Key="InverseBooleanConverter"></converters:InverseBooleanConverter>
|
||||
</ResourceDictionary>
|
||||
</UserControl.Resources>
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*"></ColumnDefinition>
|
||||
<ColumnDefinition Width="auto"></ColumnDefinition>
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid HorizontalAlignment="Stretch">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="auto"></RowDefinition>
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="auto"></ColumnDefinition>
|
||||
<ColumnDefinition Width="*"></ColumnDefinition>
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock FontSize="22" Text="Path:" Foreground="White" Margin="5" Grid.Row="0" HorizontalAlignment="Right"></TextBlock>
|
||||
<TextBox Foreground="White" Background="Transparent" Text="{Binding ElementName=_this, Path=Path, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
|
||||
BorderThickness="1" HorizontalAlignment="Stretch" Grid.Row="0" Grid.Column="1"
|
||||
FontSize="22" TextChanged="TextBox_TextChanged" Margin="5"></TextBox>
|
||||
</Grid>
|
||||
<WrapPanel Grid.Column="1">
|
||||
<local:FilePickerGlyph Width="30" Height="30" Foreground="White" VerticalAlignment="Top" Margin="5"
|
||||
Clicked="FilePickerGlyph_Clicked"></local:FilePickerGlyph>
|
||||
<local:BinButton Grid.Column="2" Height="30" Width="30" Foreground="White" VerticalAlignment="Top" Margin="5"
|
||||
Clicked="BinButton_Clicked"></local:BinButton>
|
||||
<local:StarGlyph Grid.Column="2" Height="30" Width="30" Foreground="White" VerticalAlignment="Top" Margin="5"
|
||||
Clicked="StarGlyph_Clicked" IsEnabled="{Binding ElementName=_this, Path=IsDefault, Mode=OneWay, Converter={StaticResource InverseBooleanConverter}}"></local:StarGlyph>
|
||||
</WrapPanel>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,79 @@
|
||||
using Daybreak.Models;
|
||||
using Microsoft.Win32;
|
||||
using System;
|
||||
using System.Extensions;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Extensions;
|
||||
|
||||
namespace Daybreak.Controls
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for GuildwarsPathTemplate.xaml
|
||||
/// </summary>
|
||||
public partial class GuildwarsPathTemplate : UserControl
|
||||
{
|
||||
public static readonly DependencyProperty PathProperty = DependencyPropertyExtensions.Register<GuildwarsPathTemplate, string>(nameof(Path));
|
||||
public static readonly DependencyProperty IsDefaultProperty = DependencyPropertyExtensions.Register<GuildwarsPathTemplate, bool>(nameof(IsDefault));
|
||||
|
||||
public event EventHandler RemoveClicked;
|
||||
public event EventHandler DefaultClicked;
|
||||
|
||||
public string Path
|
||||
{
|
||||
get => this.GetTypedValue<string>(PathProperty);
|
||||
set => this.SetValue(PathProperty, value);
|
||||
}
|
||||
public bool IsDefault
|
||||
{
|
||||
get => this.GetTypedValue<bool>(IsDefaultProperty);
|
||||
set => this.SetValue(IsDefaultProperty, value);
|
||||
}
|
||||
|
||||
public GuildwarsPathTemplate()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
this.DataContextChanged += GuildwarsPathTemplate_DataContextChanged;
|
||||
}
|
||||
|
||||
private void GuildwarsPathTemplate_DataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
if (e.NewValue is GuildwarsPath guildwarsPath)
|
||||
{
|
||||
this.IsDefault = guildwarsPath.Default;
|
||||
this.Path = guildwarsPath.Path;
|
||||
}
|
||||
}
|
||||
|
||||
private void TextBox_TextChanged(object sender, TextChangedEventArgs e)
|
||||
{
|
||||
this.DataContext.As<GuildwarsPath>().Path = this.Path;
|
||||
}
|
||||
|
||||
private void StarGlyph_Clicked(object sender, EventArgs e)
|
||||
{
|
||||
this.DefaultClicked?.Invoke(this, e);
|
||||
}
|
||||
|
||||
private void BinButton_Clicked(object sender, EventArgs e)
|
||||
{
|
||||
this.RemoveClicked?.Invoke(this, e);
|
||||
}
|
||||
|
||||
private void FilePickerGlyph_Clicked(object sender, EventArgs e)
|
||||
{
|
||||
var filePicker = new OpenFileDialog()
|
||||
{
|
||||
CheckFileExists = true,
|
||||
CheckPathExists = true,
|
||||
DefaultExt = "exe",
|
||||
Multiselect = false
|
||||
};
|
||||
if (filePicker.ShowDialog() is true)
|
||||
{
|
||||
this.Path = filePicker.FileName;
|
||||
this.DataContext.As<GuildwarsPath>().Path = filePicker.FileName;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
<UserControl x:Class="Daybreak.Controls.SkillTemplate"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:Daybreak.Controls"
|
||||
mc:Ignorable="d"
|
||||
x:Name="_this"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<UserControl.Resources>
|
||||
<ResourceDictionary>
|
||||
<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"></BooleanToVisibilityConverter>
|
||||
</ResourceDictionary>
|
||||
</UserControl.Resources>
|
||||
<Grid VerticalAlignment="Stretch" HorizontalAlignment="Stretch">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="*"></RowDefinition>
|
||||
<RowDefinition Height="auto"></RowDefinition>
|
||||
</Grid.RowDefinitions>
|
||||
<Image VerticalAlignment="Top" HorizontalAlignment="Left"
|
||||
Width="{Binding ElementName=_this, Path=ActualWidth, Mode=OneWay}"
|
||||
Height="{Binding ElementName=_this, Path=ActualWidth, Mode=OneWay}"
|
||||
Source="{Binding ElementName=_this, Path=ImageSource, Mode=OneWay}"
|
||||
Stretch="UniformToFill"></Image>
|
||||
<Border BorderThickness="5" BorderBrush="Black"></Border>
|
||||
<Border BorderThickness="5" BorderBrush="{Binding ElementName=_this, Path=Foreground, Mode=OneWay}"
|
||||
Opacity="{Binding ElementName=_this, Path=BorderOpacity, Mode=OneWay}"></Border>
|
||||
<Rectangle Fill="Transparent" MouseEnter="Border_MouseEnter" MouseLeave="Border_MouseLeave"
|
||||
VerticalAlignment="Stretch" HorizontalAlignment="Stretch" MouseLeftButtonDown="Rectangle_MouseLeftButtonDown"></Rectangle>
|
||||
<local:CancelButton x:Name="CancelButton" Width="30" Height="30" VerticalAlignment="Top" HorizontalAlignment="Right" Margin="10"
|
||||
Visibility="Hidden" Foreground="White" Clicked="CancelButton_Clicked" MouseEnter="Border_MouseEnter"
|
||||
MouseLeave="Border_MouseLeave"></local:CancelButton>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,121 @@
|
||||
using Daybreak.Launch;
|
||||
using Daybreak.Models.Builds;
|
||||
using Daybreak.Services.IconRetrieve;
|
||||
using System;
|
||||
using System.Extensions;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Extensions;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
|
||||
namespace Daybreak.Controls
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for SkillTemplate.xaml
|
||||
/// </summary>
|
||||
public partial class SkillTemplate : UserControl
|
||||
{
|
||||
public readonly static DependencyProperty ImageSourceProperty =
|
||||
DependencyPropertyExtensions.Register<SkillTemplate, ImageSource>(nameof(ImageSource));
|
||||
public readonly static DependencyProperty BorderOpacityProperty =
|
||||
DependencyPropertyExtensions.Register<SkillTemplate, double>(nameof(BorderOpacity), new PropertyMetadata(0d));
|
||||
|
||||
public event EventHandler<RoutedEventArgs> Clicked;
|
||||
public event EventHandler RemoveClicked;
|
||||
|
||||
private readonly IIconRetriever iconRetriever;
|
||||
|
||||
public ImageSource ImageSource
|
||||
{
|
||||
get => this.GetTypedValue<ImageSource>(ImageSourceProperty);
|
||||
set => this.SetValue(ImageSourceProperty, value);
|
||||
}
|
||||
public double BorderOpacity
|
||||
{
|
||||
get => this.GetTypedValue<double>(BorderOpacityProperty);
|
||||
set => this.SetValue(BorderOpacityProperty, value);
|
||||
}
|
||||
|
||||
public SkillTemplate()
|
||||
{
|
||||
this.iconRetriever = Launcher.ApplicationServiceManager.GetService<IIconRetriever>();
|
||||
this.InitializeComponent();
|
||||
this.DataContextChanged += SkillTemplate_DataContextChanged;
|
||||
}
|
||||
|
||||
private void SkillTemplate_DataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
if (e.NewValue is Skill skill)
|
||||
{
|
||||
if (skill != Skill.NoSkill)
|
||||
{
|
||||
Task.Run(() => GetImageStream(skill)).ContinueWith((previousTask) =>
|
||||
{
|
||||
this.Dispatcher.Invoke(() =>
|
||||
{
|
||||
this.ImageSource = GetImageSource(previousTask.Result);
|
||||
});
|
||||
});
|
||||
}
|
||||
else if (this.ImageSource is not null)
|
||||
{
|
||||
this.ImageSource = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void Border_MouseEnter(object sender, System.Windows.Input.MouseEventArgs e)
|
||||
{
|
||||
this.BorderOpacity = 1;
|
||||
this.CancelButton.Visibility = this.HasSkill() ? Visibility.Visible : Visibility.Hidden;
|
||||
}
|
||||
private void Border_MouseLeave(object sender, System.Windows.Input.MouseEventArgs e)
|
||||
{
|
||||
this.BorderOpacity = 0;
|
||||
this.CancelButton.Visibility = Visibility.Hidden;
|
||||
}
|
||||
private void Rectangle_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
|
||||
{
|
||||
this.Clicked?.Invoke(this, e);
|
||||
}
|
||||
private void CancelButton_Clicked(object sender, EventArgs e)
|
||||
{
|
||||
this.RemoveClicked?.Invoke(this, e);
|
||||
}
|
||||
|
||||
private bool HasSkill()
|
||||
{
|
||||
if (this.DataContext is Skill skill)
|
||||
{
|
||||
return skill != Skill.NoSkill;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
private async Task<Stream> GetImageStream(Skill skill)
|
||||
{
|
||||
var maybeStream = await this.iconRetriever.GetIcon(skill);
|
||||
return maybeStream.ExtractValue();
|
||||
}
|
||||
private ImageSource GetImageSource(Stream stream)
|
||||
{
|
||||
if (stream is null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return this.Dispatcher.Invoke(() =>
|
||||
{
|
||||
var bitmapImage = new BitmapImage();
|
||||
bitmapImage.BeginInit();
|
||||
bitmapImage.StreamSource = stream;
|
||||
bitmapImage.CacheOption = BitmapCacheOption.OnDemand;
|
||||
bitmapImage.EndInit();
|
||||
return bitmapImage;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Windows;
|
||||
using System.Windows.Data;
|
||||
|
||||
namespace Daybreak.Converters
|
||||
{
|
||||
public class HiddenWhenNull : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
return GetVerticalAlignment(value);
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
private object GetVerticalAlignment(object value)
|
||||
{
|
||||
if (value is null)
|
||||
{
|
||||
return Visibility.Hidden;
|
||||
}
|
||||
else
|
||||
{
|
||||
return Visibility.Visible;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
using System;
|
||||
using System.Windows.Data;
|
||||
|
||||
namespace Daybreak.Converters
|
||||
{
|
||||
public class InverseBooleanConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter,
|
||||
System.Globalization.CultureInfo culture)
|
||||
{
|
||||
if (targetType != typeof(bool))
|
||||
{
|
||||
throw new InvalidOperationException("The target must be a boolean");
|
||||
}
|
||||
|
||||
return !(bool)value;
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter,
|
||||
System.Globalization.CultureInfo culture)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Windows.Data;
|
||||
|
||||
namespace Daybreak.Converters
|
||||
{
|
||||
public class TileButtonHighlightConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
if (targetType == typeof(double) &&
|
||||
value is bool boolean)
|
||||
{
|
||||
return boolean ? 1 : 0.4;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
if (targetType == typeof(bool) &&
|
||||
value is double doubleValue)
|
||||
{
|
||||
return doubleValue == 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
{
|
||||
"GamePath": "",
|
||||
"CharacterName": "",
|
||||
"LeftBrowserDefault": "https://gwpvx.fandom.com/wiki/Special:RecentChanges?hidebots=1&hidecategorization=1&limit=50&days=7&enhanced=1&urlversion=2",
|
||||
"RightBrowserDefault": "https://wiki.guildwars.com/wiki/Quick_access_links"
|
||||
}
|
||||
+26
-15
@@ -9,43 +9,54 @@
|
||||
<CopyLocalLockFileAssemblies>false</CopyLocalLockFileAssemblies>
|
||||
<LangVersion>preview</LangVersion>
|
||||
<ApplicationIcon>Daybreak.ico</ApplicationIcon>
|
||||
<Version>0.1.3</Version>
|
||||
<Version>0.8.0</Version>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Web.WebView2" Version="1.0.774.44" />
|
||||
<PackageReference Include="HtmlAgilityPack" Version="1.11.32" />
|
||||
<PackageReference Include="Microsoft.Web.WebView2" Version="1.0.818.41" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
||||
<PackageReference Include="Slim" Version="1.2.1" />
|
||||
<PackageReference Include="SystemExtensions.NetStandard" Version="1.1.3" />
|
||||
<PackageReference Include="System.Windows.Interactivity.WPF" Version="2.0.20525" />
|
||||
<PackageReference Include="SystemExtensions.NetStandard" Version="1.1.4" />
|
||||
<PackageReference Include="WCL" Version="1.0.2" />
|
||||
<PackageReference Include="WpfExtended" Version="0.1.1" />
|
||||
<PackageReference Include="WpfExtended" Version="0.2.0" />
|
||||
<PackageReference Include="WpfScreenHelper" Version="1.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Update="Controls\StarGlyph.xaml.cs">
|
||||
<Compile Update="Controls\Buttons\HelpButton.xaml.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Update="Controls\CancelButton.xaml.cs">
|
||||
<Compile Update="Controls\Buttons\MinusButton.xaml.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Update="Controls\Glyphs\StarGlyph.xaml.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Update="Controls\Buttons\CancelButton.xaml.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Update="Daybreak.config.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Page Update="Controls\MaximizeButton.xaml">
|
||||
<Page Update="Controls\Buttons\HelpButton.xaml">
|
||||
<XamlRuntime>$(DefaultXamlRuntime)</XamlRuntime>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Update="Controls\StarGlyph.xaml">
|
||||
<Page Update="Controls\Buttons\MinusButton.xaml">
|
||||
<XamlRuntime>$(DefaultXamlRuntime)</XamlRuntime>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Update="Controls\CancelButton.xaml">
|
||||
<Page Update="Controls\Buttons\MaximizeButton.xaml">
|
||||
<XamlRuntime>$(DefaultXamlRuntime)</XamlRuntime>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Update="Controls\Glyphs\StarGlyph.xaml">
|
||||
<XamlRuntime>$(DefaultXamlRuntime)</XamlRuntime>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Update="Controls\Buttons\CancelButton.xaml">
|
||||
<XamlRuntime>$(DefaultXamlRuntime)</XamlRuntime>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
using System;
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
namespace Daybreak.Exceptions
|
||||
{
|
||||
public sealed class CredentialsNotFoundException : Exception
|
||||
{
|
||||
public CredentialsNotFoundException()
|
||||
{
|
||||
}
|
||||
|
||||
public CredentialsNotFoundException(string message) : base(message)
|
||||
{
|
||||
}
|
||||
|
||||
public CredentialsNotFoundException(SerializationInfo info, StreamingContext context) : base(info, context)
|
||||
{
|
||||
}
|
||||
|
||||
public CredentialsNotFoundException(string message, Exception innerException) : base(message, innerException)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
using System;
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
namespace Daybreak.Exceptions
|
||||
{
|
||||
public sealed class ExecutableNotFoundException : Exception
|
||||
{
|
||||
public ExecutableNotFoundException()
|
||||
{
|
||||
}
|
||||
|
||||
public ExecutableNotFoundException(string message) : base(message)
|
||||
{
|
||||
}
|
||||
|
||||
public ExecutableNotFoundException(SerializationInfo info, StreamingContext context) : base(info, context)
|
||||
{
|
||||
}
|
||||
|
||||
public ExecutableNotFoundException(string message, Exception innerException) : base(message, innerException)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9,6 +9,8 @@ using Microsoft.Web.WebView2.Wpf;
|
||||
using Slim;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Extensions;
|
||||
@@ -45,6 +47,18 @@ namespace Daybreak.Launch
|
||||
MessageBox.Show(fatalException.ToString());
|
||||
return false;
|
||||
}
|
||||
else if (e is AggregateException aggregateException)
|
||||
{
|
||||
if (aggregateException.InnerExceptions.FirstOrDefault() is COMException comException &&
|
||||
comException.Message.Contains("Invalid window handle"))
|
||||
{
|
||||
/*
|
||||
* Ignore exception caused by browser failing to initialize due to missing window.
|
||||
* Likely caused by switching windows before browser was initialized.
|
||||
*/
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
MessageBox.Show(e.ToString());
|
||||
return true;
|
||||
|
||||
@@ -69,8 +69,6 @@
|
||||
</controls:ImageViewer.Effect>
|
||||
</controls:ImageViewer>
|
||||
</Border>
|
||||
<Grid x:Name="Container" Grid.Row="1">
|
||||
</Grid>
|
||||
<wcl:TitleBar x:Name="Titlebar"
|
||||
Background="Transparent" MouseLeftButtonDown="TitleBar_MouseLeftButtonDown"
|
||||
WindowState="Normal" MinimizeButtonClicked="TitleBar_MinimizeButtonClicked"
|
||||
@@ -80,10 +78,15 @@
|
||||
Foreground="{Binding ElementName=_this, Path=Foreground, Mode=OneWay}"></wcl:TitleBar>
|
||||
<ToggleButton Style="{StaticResource Window_SettingsButton}" Width="50" Height="30" HorizontalAlignment="Right"
|
||||
Margin="0, 0, 150, 0" Foreground="{Binding ElementName=_this, Path=Foreground, Mode=OneWay}" Click="SettingsButton_Clicked"></ToggleButton>
|
||||
<TextBox Grid.Row="1" Background="Transparent" BorderBrush="Transparent" BorderThickness="0" Opacity="0.6"
|
||||
Text="{Binding ElementName=_this, Path=CreditText, Mode=OneWay}" IsReadOnly="True" VerticalAlignment="Bottom"
|
||||
<controls:OpaqueButton Grid.Row="1" Background="Transparent" BorderBrush="Transparent" BorderThickness="0" Opacity="0.6"
|
||||
Text="{Binding ElementName=_this, Path=CreditText, Mode=OneWay}" VerticalAlignment="Bottom"
|
||||
HorizontalAlignment="Right" Margin="0, 0, 20, 30" FontSize="22" Foreground="{Binding ElementName=_this, Path=Foreground, Mode=OneWay}"
|
||||
PreviewMouseLeftButtonDown="CreditTextBox_MouseLeftButtonDown" Cursor="Hand"></TextBox>
|
||||
Clicked="CreditTextBox_MouseLeftButtonDown" Cursor="Hand"></controls:OpaqueButton>
|
||||
<TextBox Grid.Row="1" Background="Transparent" BorderBrush="Transparent" BorderThickness="0" Opacity="0.6"
|
||||
Text="{Binding ElementName=_this, Path=CurrentVersionText, Mode=OneWay}" IsReadOnly="True" VerticalAlignment="Bottom"
|
||||
HorizontalAlignment="Right" Margin="0, 0, 20, 10" FontSize="10" Foreground="{Binding ElementName=_this, Path=Foreground, Mode=OneWay}"></TextBox>
|
||||
<Grid x:Name="Container" Grid.Row="1">
|
||||
</Grid>
|
||||
<wcl:Border OnResize="Border_OnResize" Grid.RowSpan="2" Active="True"></wcl:Border>
|
||||
</Grid>
|
||||
</Window>
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
using Daybreak.Services.Bloogum;
|
||||
using Daybreak.Services.Runtime;
|
||||
using Daybreak.Services.Screenshots;
|
||||
using Daybreak.Services.Updater;
|
||||
using Daybreak.Services.ViewManagement;
|
||||
using Daybreak.Views;
|
||||
using Pepa.Wpf.Utilities;
|
||||
@@ -22,10 +24,12 @@ namespace Daybreak.Launch
|
||||
public partial class MainWindow : Window
|
||||
{
|
||||
public static readonly DependencyProperty CreditTextProperty = DependencyPropertyExtensions.Register<MainWindow, string>(nameof(CreditText));
|
||||
public static readonly DependencyProperty CurrentVersionTextProperty = DependencyPropertyExtensions.Register<MainWindow, string>(nameof(CurrentVersionText));
|
||||
|
||||
private readonly IViewManager viewManager;
|
||||
private readonly IScreenshotProvider screenshotProvider;
|
||||
private readonly IBloogumClient bloogumClient;
|
||||
private readonly IApplicationUpdater applicationUpdater;
|
||||
private readonly CancellationTokenSource cancellationToken = new();
|
||||
|
||||
public string CreditText
|
||||
@@ -34,21 +38,30 @@ namespace Daybreak.Launch
|
||||
set => this.SetValue(CreditTextProperty, value);
|
||||
}
|
||||
|
||||
public string CurrentVersionText
|
||||
{
|
||||
get => this.GetTypedValue<string>(CurrentVersionTextProperty);
|
||||
set => this.SetValue(CurrentVersionTextProperty, value);
|
||||
}
|
||||
|
||||
public MainWindow(
|
||||
IViewManager viewManager,
|
||||
IScreenshotProvider screenshotProvider,
|
||||
IBloogumClient bloogumClient)
|
||||
IBloogumClient bloogumClient,
|
||||
IApplicationUpdater applicationUpdater)
|
||||
{
|
||||
this.viewManager = viewManager.ThrowIfNull(nameof(viewManager));
|
||||
this.screenshotProvider = screenshotProvider.ThrowIfNull(nameof(screenshotProvider));
|
||||
this.bloogumClient = bloogumClient.ThrowIfNull(nameof(bloogumClient));
|
||||
InitializeComponent();
|
||||
this.applicationUpdater = applicationUpdater.ThrowIfNull(nameof(applicationUpdater));
|
||||
this.InitializeComponent();
|
||||
this.CurrentVersionText = this.applicationUpdater.CurrentVersion;
|
||||
}
|
||||
|
||||
private void Window_Loaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
this.viewManager.ShowView<MainView>();
|
||||
this.SetupImageCycle();
|
||||
this.CheckForUpdates();
|
||||
}
|
||||
|
||||
private void TitleBar_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
|
||||
@@ -116,10 +129,10 @@ namespace Daybreak.Launch
|
||||
|
||||
private void SettingsButton_Clicked(object sender, EventArgs e)
|
||||
{
|
||||
this.viewManager.ShowView<SettingsView>();
|
||||
this.viewManager.ShowView<SettingsCategoryView>();
|
||||
}
|
||||
|
||||
private void CreditTextBox_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
|
||||
private void CreditTextBox_MouseLeftButtonDown(object sender, EventArgs e)
|
||||
{
|
||||
if (Uri.TryCreate(this.CreditText, UriKind.Absolute, out var uri))
|
||||
{
|
||||
@@ -145,6 +158,25 @@ namespace Daybreak.Launch
|
||||
}
|
||||
}
|
||||
|
||||
private async void CheckForUpdates()
|
||||
{
|
||||
var updateAvailable = await this.applicationUpdater.UpdateAvailable().ConfigureAwait(true);
|
||||
if (updateAvailable)
|
||||
{
|
||||
this.viewManager.ShowView<AskUpdateView>();
|
||||
}
|
||||
else
|
||||
{
|
||||
this.viewManager.ShowView<MainView>();
|
||||
this.PeriodicallyCheckForUpdates();
|
||||
}
|
||||
}
|
||||
|
||||
private void PeriodicallyCheckForUpdates()
|
||||
{
|
||||
this.applicationUpdater.PeriodicallyCheckForUpdates();
|
||||
}
|
||||
|
||||
private static Color GetAverageColor(BitmapSource bitmap)
|
||||
{
|
||||
var format = bitmap.Format;
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Converters;
|
||||
|
||||
namespace Daybreak.Models.Browser
|
||||
{
|
||||
public class BrowserPayload
|
||||
{
|
||||
[JsonConverter(typeof(StringEnumConverter))]
|
||||
public enum PayloadKeys
|
||||
{
|
||||
ContextMenu
|
||||
}
|
||||
|
||||
[JsonProperty("Key")]
|
||||
public PayloadKeys Key { get; set; }
|
||||
}
|
||||
|
||||
public sealed class BrowserPayload<T> : BrowserPayload
|
||||
{
|
||||
[JsonProperty("Value")]
|
||||
public T Value { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Daybreak.Models.Browser
|
||||
{
|
||||
public sealed class OnContextMenuPayload
|
||||
{
|
||||
[JsonProperty("X")]
|
||||
public double X { get; set; }
|
||||
[JsonProperty("Y")]
|
||||
public double Y { get; set; }
|
||||
[JsonProperty("Selection")]
|
||||
public string Selection { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,143 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Daybreak.Models.Builds
|
||||
{
|
||||
public sealed class Attribute
|
||||
{
|
||||
public static Attribute FastCasting { get; } = new() { Name = "Fast Casting", Id = 0 };
|
||||
public static Attribute IllusionMagic { get; } = new() { Name = "Illusion Magic", Id = 1 };
|
||||
public static Attribute DominationMagic { get; } = new() { Name = "Domination Magic", Id = 2 };
|
||||
public static Attribute InspirationMagic { get; } = new() { Name = "Inspiration Magic", Id = 3 };
|
||||
public static Attribute BloodMagic { get; } = new() { Name = "Blood Magic", Id = 4 };
|
||||
public static Attribute DeathMagic { get; } = new() { Name = "Death Magic", Id = 5 };
|
||||
public static Attribute SoulReaping { get; } = new() { Name = "Soul Reaping", Id = 6 };
|
||||
public static Attribute Curses { get; } = new() { Name = "Curses", Id = 7 };
|
||||
public static Attribute AirMagic { get; } = new() { Name = "Air Magic", Id = 8 };
|
||||
public static Attribute EarthMagic { get; } = new() { Name = "Earth Magic", Id = 9 };
|
||||
public static Attribute FireMagic { get; } = new() { Name = "Fire Magic", Id = 10 };
|
||||
public static Attribute WaterMagic { get; } = new() { Name = "Water Magic", Id = 11 };
|
||||
public static Attribute EnergyStorage { get; } = new() { Name = "Energy Storage", Id = 12 };
|
||||
public static Attribute HealingPrayers { get; } = new() { Name = "Healing Prayers", Id = 13 };
|
||||
public static Attribute SmitingPrayers { get; } = new() { Name = "Smiting Prayers", Id = 14 };
|
||||
public static Attribute ProtectionPrayers { get; } = new() { Name = "Protection Prayers", Id = 15 };
|
||||
public static Attribute DivineFavor { get; } = new() { Name = "Divine Favor", Id = 16 };
|
||||
public static Attribute Strength { get; } = new() { Name = "Strength", Id = 17 };
|
||||
public static Attribute AxeMastery { get; } = new() { Name = "Axe Mastery", Id = 18 };
|
||||
public static Attribute HammerMastery { get; } = new() { Name = "Hammer Mastery", Id = 19 };
|
||||
public static Attribute Swordsmanship { get; } = new() { Name = "Swordsmanship", Id = 20};
|
||||
public static Attribute Tactics { get; } = new() { Name = "Tactics", Id = 21 };
|
||||
public static Attribute BeastMastery { get; } = new() { Name = "Beast Mastery", Id = 22 };
|
||||
public static Attribute Expertise { get; } = new() { Name = "Expertise", Id = 23 };
|
||||
public static Attribute WildernessSurvival { get; } = new() { Name = "Wilderness Survival", Id = 24 };
|
||||
public static Attribute Marksmanship { get; } = new() { Name = "Marksmanship", Id = 25 };
|
||||
public static Attribute DaggerMastery { get; } = new() { Name = "Dagger Mastery", Id = 29 };
|
||||
public static Attribute DeadlyArts { get; } = new() { Name = "Deadly Arts", Id = 30 };
|
||||
public static Attribute ShadowArts { get; } = new() { Name = "Shadow Arts", Id = 31 };
|
||||
public static Attribute Communing { get; } = new() { Name = "Communing", Id = 32 };
|
||||
public static Attribute RestorationMagic { get; } = new() { Name = "Restoration Magic", Id = 33 };
|
||||
public static Attribute ChannelingMagic { get; } = new() { Name = "Channeling Magic", Id = 34 };
|
||||
public static Attribute CriticalStrikes { get; } = new() { Name = "Critical Strikes", Id = 35 };
|
||||
public static Attribute SpawningPower { get; } = new() { Name = "Spawning Power", Id = 36 };
|
||||
public static Attribute SpearMastery { get; } = new() { Name = "Spear Mastery", Id = 37 };
|
||||
public static Attribute Command { get; } = new() { Name = "Command", Id = 38 };
|
||||
public static Attribute Motivation { get; } = new() { Name = "Motivation", Id = 39 };
|
||||
public static Attribute Leadership { get; } = new() { Name = "Leadership", Id = 40 };
|
||||
public static Attribute ScytheMastery { get; } = new() { Name = "Scythe Mastery", Id = 41 };
|
||||
public static Attribute WindPrayers { get; } = new() { Name = "Wind Prayers", Id = 42 };
|
||||
public static Attribute EarthPrayers { get; } = new() { Name = "Earth Prayers", Id = 43 };
|
||||
public static Attribute Mysticism { get; } = new() { Name = "Mysticism", Id = 44 };
|
||||
public static IEnumerable<Attribute> Attributes { get; } = new List<Attribute>
|
||||
{
|
||||
FastCasting,
|
||||
IllusionMagic,
|
||||
DominationMagic,
|
||||
InspirationMagic,
|
||||
BloodMagic,
|
||||
DeathMagic,
|
||||
SoulReaping,
|
||||
Curses,
|
||||
AirMagic,
|
||||
EarthMagic,
|
||||
FireMagic,
|
||||
WaterMagic,
|
||||
EnergyStorage,
|
||||
HealingPrayers,
|
||||
SmitingPrayers,
|
||||
ProtectionPrayers,
|
||||
DivineFavor,
|
||||
Strength,
|
||||
AxeMastery,
|
||||
HammerMastery,
|
||||
Swordsmanship,
|
||||
Tactics,
|
||||
BeastMastery,
|
||||
Expertise,
|
||||
WildernessSurvival,
|
||||
Marksmanship,
|
||||
DaggerMastery,
|
||||
DeadlyArts,
|
||||
ShadowArts,
|
||||
Communing,
|
||||
RestorationMagic,
|
||||
ChannelingMagic,
|
||||
CriticalStrikes,
|
||||
SpawningPower,
|
||||
SpearMastery,
|
||||
Command,
|
||||
Motivation,
|
||||
Leadership,
|
||||
ScytheMastery,
|
||||
EarthPrayers,
|
||||
WindPrayers,
|
||||
EarthMagic,
|
||||
Mysticism
|
||||
};
|
||||
|
||||
public static bool TryParse(int id, out Attribute attribute)
|
||||
{
|
||||
attribute = Attributes.Where(attr => attr.Id == id).FirstOrDefault();
|
||||
if (attribute is null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
public static bool TryParse(string name, out Attribute attribute)
|
||||
{
|
||||
attribute = Attributes.Where(attr => attr.Name == name).FirstOrDefault();
|
||||
if (attribute is null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
public static Attribute Parse(int id)
|
||||
{
|
||||
if (TryParse(id, out var attribute) is false)
|
||||
{
|
||||
throw new InvalidOperationException($"Could not find an attribute with id {id}");
|
||||
}
|
||||
|
||||
return attribute;
|
||||
}
|
||||
public static Attribute Parse(string name)
|
||||
{
|
||||
if (TryParse(name, out var attribute) is false)
|
||||
{
|
||||
throw new InvalidOperationException($"Could not find an attribute with name {name}");
|
||||
}
|
||||
|
||||
return attribute;
|
||||
}
|
||||
|
||||
public int Id { get; private set; }
|
||||
public string Name { get; private set; }
|
||||
private Attribute()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
using System.ComponentModel;
|
||||
|
||||
namespace Daybreak.Models.Builds
|
||||
{
|
||||
public sealed class AttributeEntry : INotifyPropertyChanged
|
||||
{
|
||||
private Attribute attribute;
|
||||
private int points;
|
||||
|
||||
public Attribute Attribute
|
||||
{
|
||||
get => this.attribute;
|
||||
set
|
||||
{
|
||||
this.attribute = value;
|
||||
this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Attribute)));
|
||||
}
|
||||
}
|
||||
public int Points
|
||||
{
|
||||
get => this.points;
|
||||
set
|
||||
{
|
||||
this.points = value;
|
||||
this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Points)));
|
||||
}
|
||||
}
|
||||
|
||||
public event PropertyChangedEventHandler PropertyChanged;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Daybreak.Models.Builds
|
||||
{
|
||||
public sealed class Build
|
||||
{
|
||||
public BuildMetadata BuildMetadata { get; set; }
|
||||
public Profession Primary { get; set; } = Profession.None;
|
||||
public Profession Secondary { get; set; } = Profession.None;
|
||||
public List<AttributeEntry> Attributes { get; set; } = new();
|
||||
public List<Skill> Skills { get; set; } = new() { Skill.NoSkill, Skill.NoSkill, Skill.NoSkill, Skill.NoSkill, Skill.NoSkill, Skill.NoSkill, Skill.NoSkill, Skill.NoSkill };
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
using System.ComponentModel;
|
||||
|
||||
namespace Daybreak.Models.Builds
|
||||
{
|
||||
public sealed class BuildEntry : INotifyPropertyChanged
|
||||
{
|
||||
public event PropertyChangedEventHandler PropertyChanged;
|
||||
private string name;
|
||||
private Build build;
|
||||
|
||||
public string PreviousName { get; set; }
|
||||
public string Name
|
||||
{
|
||||
get => this.name;
|
||||
set
|
||||
{
|
||||
this.name = value;
|
||||
this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Name)));
|
||||
}
|
||||
}
|
||||
public Build Build
|
||||
{
|
||||
get => this.build;
|
||||
set
|
||||
{
|
||||
this.build = value;
|
||||
this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Build)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Daybreak.Models.Builds
|
||||
{
|
||||
public sealed class BuildMetadata
|
||||
{
|
||||
public List<int> Base64Decoded { get; set; }
|
||||
public List<string> BinaryDecoded { get; set; }
|
||||
public int Header { get; set; }
|
||||
public int VersionNumber { get; set; }
|
||||
public int ProfessionIdLength { get; set; }
|
||||
public int PrimaryProfessionId { get; set; }
|
||||
public int SecondaryProfessionId { get; set; }
|
||||
public int AttributeCount { get; set; }
|
||||
public int AttributesLength { get; set; }
|
||||
public int SkillsLength { get; set; }
|
||||
public bool TailPresent { get; set; }
|
||||
public bool NewTemplate { get; set; }
|
||||
public List<int> SkillIds { get; set; } = new();
|
||||
public List<int> AttributesIds { get; set; } = new();
|
||||
public List<int> AttributePoints { get; set; } = new();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Daybreak.Models.Builds
|
||||
{
|
||||
public sealed class Profession
|
||||
{
|
||||
public static Profession None { get; } = new() { Name = "None", Id = 0, };
|
||||
public static Profession Warrior { get; } = new() { Name = "Warrior", Id = 1, PrimaryAttribute = Attribute.Strength, Attributes = new List<Attribute> { Attribute.AxeMastery, Attribute.HammerMastery, Attribute.Swordsmanship, Attribute.Tactics } };
|
||||
public static Profession Ranger { get; } = new() { Name = "Ranger", Id = 2, PrimaryAttribute = Attribute.Expertise, Attributes = new List<Attribute> { Attribute.BeastMastery, Attribute.Marksmanship, Attribute.WildernessSurvival } };
|
||||
public static Profession Monk { get; } = new() { Name = "Monk", Id = 3, PrimaryAttribute = Attribute.DivineFavor, Attributes = new List<Attribute> { Attribute.HealingPrayers, Attribute.SmitingPrayers, Attribute.ProtectionPrayers } };
|
||||
public static Profession Necromancer { get; } = new() { Name = "Necromancer", Id = 4, PrimaryAttribute = Attribute.SoulReaping, Attributes = new List<Attribute> { Attribute.Curses, Attribute.BloodMagic, Attribute.DeathMagic } };
|
||||
public static Profession Mesmer { get; } = new() { Name = "Mesmer", Id = 5, PrimaryAttribute = Attribute.FastCasting, Attributes = new List<Attribute> { Attribute.DominationMagic, Attribute.IllusionMagic, Attribute.InspirationMagic } };
|
||||
public static Profession Elementalist { get; } = new() { Name = "Elementalist", Id = 6, PrimaryAttribute = Attribute.EnergyStorage, Attributes = new List<Attribute> { Attribute.AirMagic, Attribute.EarthMagic, Attribute.FireMagic, Attribute.WaterMagic } };
|
||||
public static Profession Assassin { get; } = new() { Name = "Assassin", Id = 7, PrimaryAttribute = Attribute.CriticalStrikes, Attributes = new List<Attribute> { Attribute.DaggerMastery, Attribute.DeadlyArts, Attribute.ShadowArts } };
|
||||
public static Profession Ritualist { get; } = new() { Name = "Ritualist", Id = 8, PrimaryAttribute = Attribute.SpawningPower, Attributes = new List<Attribute> { Attribute.ChannelingMagic, Attribute.Communing, Attribute.RestorationMagic } };
|
||||
public static Profession Paragon { get; } = new() { Name = "Paragon", Id = 9, PrimaryAttribute = Attribute.Leadership, Attributes = new List<Attribute> { Attribute.Command, Attribute.Motivation, Attribute.SpearMastery } };
|
||||
public static Profession Dervish { get; } = new() { Name = "Dervish", Id = 10, PrimaryAttribute = Attribute.Mysticism, Attributes = new List<Attribute> { Attribute.EarthPrayers, Attribute.ScytheMastery, Attribute.WindPrayers } };
|
||||
public static IEnumerable<Profession> Professions { get; } = new List<Profession>
|
||||
{
|
||||
None,
|
||||
Warrior,
|
||||
Ranger,
|
||||
Monk,
|
||||
Necromancer,
|
||||
Mesmer,
|
||||
Elementalist,
|
||||
Assassin,
|
||||
Ritualist,
|
||||
Paragon,
|
||||
Dervish
|
||||
};
|
||||
public static bool TryParse(int id, out Profession profession)
|
||||
{
|
||||
profession = Professions.Where(prof => prof.Id == id).FirstOrDefault();
|
||||
if (profession is null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
public static bool TryParse(string name, out Profession profession)
|
||||
{
|
||||
profession = Professions.Where(prof => prof.Name == name).FirstOrDefault();
|
||||
if (profession is null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
public static Profession Parse(int id)
|
||||
{
|
||||
if (TryParse(id, out var profession) is false)
|
||||
{
|
||||
throw new InvalidOperationException($"Could not find a profession with id {id}");
|
||||
}
|
||||
|
||||
return profession;
|
||||
}
|
||||
public static Profession Parse(string name)
|
||||
{
|
||||
if (TryParse(name, out var profession) is false)
|
||||
{
|
||||
throw new InvalidOperationException($"Could not find a profession with name {name}");
|
||||
}
|
||||
|
||||
return profession;
|
||||
}
|
||||
|
||||
public string Name { get; private set; }
|
||||
public int Id { get; set; }
|
||||
public Attribute PrimaryAttribute { get; private set; }
|
||||
public List<Attribute> Attributes { get; private set; }
|
||||
private Profession()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,11 @@
|
||||
using System;
|
||||
|
||||
namespace Daybreak.Models
|
||||
{
|
||||
public sealed class ElevationRequest
|
||||
{
|
||||
public object DataContext { get; set; }
|
||||
public Type View { get; set; }
|
||||
public string MessageToUser { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
namespace Daybreak.Models
|
||||
{
|
||||
public enum ExecutionPolicies
|
||||
{
|
||||
AllSigned,
|
||||
Bypass,
|
||||
Default,
|
||||
RemoteSigned,
|
||||
Restricted,
|
||||
Undefined,
|
||||
Unrestricted
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Daybreak.Models
|
||||
{
|
||||
public sealed class GuildwarsPath
|
||||
{
|
||||
[JsonProperty("path")]
|
||||
public string Path { get; set; }
|
||||
[JsonProperty("default")]
|
||||
public bool Default { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,8 @@
|
||||
public sealed class LoginCredentials
|
||||
{
|
||||
public string Username { get; set; }
|
||||
public SecureString Password { get; set; }
|
||||
public string Password { get; set; }
|
||||
public string CharacterName { get; set; }
|
||||
public bool Default { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Daybreak.Models
|
||||
{
|
||||
public sealed class ProtectedLoginCredentials
|
||||
{
|
||||
[JsonProperty("ProtectedUsername")]
|
||||
public string ProtectedUsername { get; set; }
|
||||
[JsonProperty("ProtectedPassword")]
|
||||
public string ProtectedPassword { get; set; }
|
||||
[JsonProperty("CharacterName")]
|
||||
public string CharacterName { get; set; }
|
||||
[JsonProperty("Default")]
|
||||
public bool Default { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
using System.ComponentModel;
|
||||
|
||||
namespace Daybreak.Models
|
||||
{
|
||||
public sealed class UpdateStatus : INotifyPropertyChanged
|
||||
{
|
||||
public static readonly UpdateStep StartingStep = new("Starting");
|
||||
public static readonly UpdateStep CheckingLatestVersion = new("Checking latest version");
|
||||
public static UpdateStep Downloading(double progress) => new DownloadUpdateStep("Downloading", progress);
|
||||
public static readonly UpdateStep DownloadFinished = new("Download finished. Application will restart in order to apply the update.");
|
||||
|
||||
private UpdateStep currentStep = StartingStep;
|
||||
|
||||
public event PropertyChangedEventHandler PropertyChanged;
|
||||
|
||||
public UpdateStep CurrentStep
|
||||
{
|
||||
get => this.currentStep;
|
||||
set
|
||||
{
|
||||
this.currentStep = value;
|
||||
this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(CurrentStep)));
|
||||
}
|
||||
}
|
||||
|
||||
public class UpdateStep
|
||||
{
|
||||
public string Name { get; }
|
||||
internal UpdateStep(string name)
|
||||
{
|
||||
this.Name = name;
|
||||
}
|
||||
}
|
||||
public class DownloadUpdateStep : UpdateStep
|
||||
{
|
||||
internal DownloadUpdateStep(string name, double progress) : base(name)
|
||||
{
|
||||
this.Progress = progress;
|
||||
}
|
||||
|
||||
public double Progress { get; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,85 +0,0 @@
|
||||
using Daybreak.Services.Configuration;
|
||||
using Daybreak.Services.Credentials;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Extensions;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
namespace Daybreak.Services.ApplicationDetection
|
||||
{
|
||||
public class ApplicationDetector : IApplicationDetector
|
||||
{
|
||||
private const string ToolboxProcessName = "GWToolbox";
|
||||
private const string ProcessName = "gw";
|
||||
|
||||
private readonly IConfigurationManager configurationManager;
|
||||
private readonly ICredentialManager credentialManager;
|
||||
|
||||
public bool IsGuildwarsRunning => GuildwarsProcessDetected();
|
||||
public bool IsToolboxRunning => GuildwarsToolboxProcessDetected();
|
||||
|
||||
public ApplicationDetector(
|
||||
IConfigurationManager configurationManager,
|
||||
ICredentialManager credentialManager)
|
||||
{
|
||||
this.credentialManager = credentialManager.ThrowIfNull(nameof(credentialManager));
|
||||
this.configurationManager = configurationManager.ThrowIfNull(nameof(configurationManager));
|
||||
}
|
||||
|
||||
public void LaunchGuildwars()
|
||||
{
|
||||
var configuration = this.configurationManager.GetConfiguration();
|
||||
var executable = configuration.GamePath;
|
||||
if (File.Exists(executable) is false)
|
||||
{
|
||||
throw new InvalidOperationException($"Guildwars executable doesn't exist at {executable}");
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(configuration.CharacterName))
|
||||
{
|
||||
throw new InvalidOperationException($"No character name set");
|
||||
}
|
||||
|
||||
var auth = this.credentialManager.GetCredentials();
|
||||
auth.Do(
|
||||
onSome: (credentials) =>
|
||||
{
|
||||
if (Process.Start(executable, new List<string> { "-email", credentials.Username, "-password", credentials.Password, "-character", configuration.CharacterName }) is null)
|
||||
{
|
||||
throw new InvalidOperationException($"Unable to launch {executable}");
|
||||
}
|
||||
},
|
||||
onNone: () =>
|
||||
{
|
||||
throw new InvalidOperationException($"No credentials available");
|
||||
});
|
||||
}
|
||||
|
||||
public void LaunchGuildwarsToolbox()
|
||||
{
|
||||
var configuration = this.configurationManager.GetConfiguration();
|
||||
var executable = configuration.ToolboxPath;
|
||||
if (File.Exists(executable) is false)
|
||||
{
|
||||
throw new InvalidOperationException($"Guildwars executable doesn't exist at {executable}");
|
||||
}
|
||||
|
||||
if (Process.Start(executable) is null)
|
||||
{
|
||||
throw new InvalidOperationException($"Unable to launch {executable}");
|
||||
}
|
||||
}
|
||||
|
||||
private static bool GuildwarsProcessDetected()
|
||||
{
|
||||
return Process.GetProcessesByName(ProcessName).FirstOrDefault() is not null;
|
||||
}
|
||||
|
||||
private static bool GuildwarsToolboxProcessDetected()
|
||||
{
|
||||
return Process.GetProcessesByName(ToolboxProcessName).FirstOrDefault() is not null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
namespace Daybreak.Services.ApplicationDetection
|
||||
{
|
||||
public interface IApplicationDetector
|
||||
{
|
||||
bool IsGuildwarsRunning { get; }
|
||||
bool IsToolboxRunning { get; }
|
||||
void LaunchGuildwars();
|
||||
void LaunchGuildwarsToolbox();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,284 @@
|
||||
using Daybreak.Exceptions;
|
||||
using Daybreak.Services.Configuration;
|
||||
using Daybreak.Services.Credentials;
|
||||
using Daybreak.Services.Logging;
|
||||
using Daybreak.Services.Mutex;
|
||||
using Daybreak.Services.Privilege;
|
||||
using Daybreak.Utils;
|
||||
using Daybreak.Views;
|
||||
using Microsoft.Win32;
|
||||
using Pepa.Wpf.Utilities;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Extensions;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Security;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
|
||||
namespace Daybreak.Services.ApplicationLauncher
|
||||
{
|
||||
public class ApplicationLauncher : IApplicationLauncher
|
||||
{
|
||||
private const string TexModProcessName = "TexMod";
|
||||
private const string UModProcessName = "uMod";
|
||||
private const string ToolboxProcessName = "GWToolbox";
|
||||
private const string ProcessName = "gw";
|
||||
private const string ArenaNetMutex = "AN-Mute";
|
||||
|
||||
private readonly IConfigurationManager configurationManager;
|
||||
private readonly ICredentialManager credentialManager;
|
||||
private readonly IMutexHandler mutexHandler;
|
||||
private readonly ILogger logger;
|
||||
private readonly IPrivilegeManager privilegeManager;
|
||||
|
||||
public bool IsTexmodRunning => TexModProcessDetected();
|
||||
public bool IsGuildwarsRunning => this.GuildwarsProcessDetected();
|
||||
public bool IsToolboxRunning => GuildwarsToolboxProcessDetected();
|
||||
|
||||
public ApplicationLauncher(
|
||||
IConfigurationManager configurationManager,
|
||||
ICredentialManager credentialManager,
|
||||
IMutexHandler mutexHandler,
|
||||
ILogger logger,
|
||||
IPrivilegeManager privilegeManager)
|
||||
{
|
||||
this.logger = logger.ThrowIfNull(nameof(logger));
|
||||
this.mutexHandler = mutexHandler.ThrowIfNull(nameof(mutexHandler));
|
||||
this.credentialManager = credentialManager.ThrowIfNull(nameof(credentialManager));
|
||||
this.configurationManager = configurationManager.ThrowIfNull(nameof(configurationManager));
|
||||
this.privilegeManager = privilegeManager.ThrowIfNull(nameof(privilegeManager));
|
||||
}
|
||||
|
||||
public async Task LaunchGuildwars()
|
||||
{
|
||||
var configuration = this.configurationManager.GetConfiguration();
|
||||
var auth = await this.credentialManager.GetDefaultCredentials().ConfigureAwait(false);
|
||||
auth.Do(
|
||||
onSome: (credentials) =>
|
||||
{
|
||||
if (configuration.ExperimentalFeatures.MultiLaunchSupport is true)
|
||||
{
|
||||
if (this.privilegeManager.AdminPrivileges is false)
|
||||
{
|
||||
this.privilegeManager.RequestAdminPrivileges<MainView>("You need administrator rights in order to start using multi-launch");
|
||||
return;
|
||||
}
|
||||
|
||||
ClearGwLocks();
|
||||
}
|
||||
|
||||
LaunchGuildwarsProcess(credentials.Username, credentials.Password, credentials.CharacterName);
|
||||
},
|
||||
onNone: () =>
|
||||
{
|
||||
throw new CredentialsNotFoundException($"No credentials available");
|
||||
});
|
||||
}
|
||||
|
||||
public Task LaunchGuildwarsToolbox()
|
||||
{
|
||||
return Task.Run(() =>
|
||||
{
|
||||
var configuration = this.configurationManager.GetConfiguration();
|
||||
var executable = configuration.ToolboxPath;
|
||||
if (File.Exists(executable) is false)
|
||||
{
|
||||
throw new ExecutableNotFoundException($"Guildwars executable doesn't exist at {executable}");
|
||||
}
|
||||
|
||||
if (Process.Start(executable) is null)
|
||||
{
|
||||
throw new InvalidOperationException($"Unable to launch {executable}");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public Task LaunchTexmod()
|
||||
{
|
||||
return Task.Run(() =>
|
||||
{
|
||||
var configuration = this.configurationManager.GetConfiguration();
|
||||
var executable = configuration.TexmodPath;
|
||||
if (File.Exists(executable) is false)
|
||||
{
|
||||
throw new ExecutableNotFoundException($"Texmod executable doesn't exist at {executable}");
|
||||
}
|
||||
|
||||
if (Process.Start(executable) is null)
|
||||
{
|
||||
throw new InvalidOperationException($"Unable to launch {executable}");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void RestartDaybreakAsAdmin()
|
||||
{
|
||||
this.logger.LogInformation("Restarting daybreak with admin rights");
|
||||
var processName = Process.GetCurrentProcess()?.MainModule?.FileName;
|
||||
if (processName.IsNullOrWhiteSpace() || File.Exists(processName) is false)
|
||||
{
|
||||
throw new InvalidOperationException("Unable to find executable. Aborting restart");
|
||||
}
|
||||
|
||||
var process = new Process()
|
||||
{
|
||||
StartInfo = new()
|
||||
{
|
||||
Verb = "runas",
|
||||
WorkingDirectory = Environment.CurrentDirectory,
|
||||
UseShellExecute = true,
|
||||
FileName = processName
|
||||
}
|
||||
};
|
||||
if (process.Start() is false)
|
||||
{
|
||||
throw new InvalidOperationException($"Unable to start {processName} as admin");
|
||||
}
|
||||
|
||||
Application.Current.Shutdown();
|
||||
}
|
||||
|
||||
private void LaunchGuildwarsProcess(string email, Models.SecureString password, string character)
|
||||
{
|
||||
var executable = this.configurationManager.GetConfiguration().GuildwarsPaths.Where(path => path.Default).FirstOrDefault();
|
||||
if (executable is null)
|
||||
{
|
||||
throw new ExecutableNotFoundException($"No executable selected");
|
||||
}
|
||||
|
||||
if (File.Exists(executable.Path) is false)
|
||||
{
|
||||
throw new ExecutableNotFoundException($"Guildwars executable doesn't exist at {executable}");
|
||||
}
|
||||
|
||||
var args = new List<string>()
|
||||
{
|
||||
"-email",
|
||||
email,
|
||||
"-password",
|
||||
password
|
||||
};
|
||||
if (!string.IsNullOrWhiteSpace(character))
|
||||
{
|
||||
args.Add("-character");
|
||||
args.Add(character);
|
||||
}
|
||||
|
||||
var identity = this.configurationManager.GetConfiguration().ExperimentalFeatures.LaunchGuildwarsAsCurrentUser ?
|
||||
System.Security.Principal.WindowsIdentity.GetCurrent().Name :
|
||||
System.Security.Principal.WindowsIdentity.GetAnonymous().Name;
|
||||
this.logger.LogInformation($"Launching guildwars as [{identity}] identity");
|
||||
var process = new Process()
|
||||
{
|
||||
StartInfo = new ProcessStartInfo
|
||||
{
|
||||
Arguments = string.Join(" ", args),
|
||||
UserName = identity
|
||||
}
|
||||
};
|
||||
if (Process.Start(executable.Path, args) is null)
|
||||
{
|
||||
throw new InvalidOperationException($"Unable to launch {executable}");
|
||||
}
|
||||
}
|
||||
|
||||
private bool GuildwarsProcessDetected()
|
||||
{
|
||||
if (this.configurationManager.GetConfiguration().ExperimentalFeatures.MultiLaunchSupport is true)
|
||||
{
|
||||
try
|
||||
{
|
||||
var path = this.configurationManager.GetConfiguration().GuildwarsPaths.Where(path => path.Default).FirstOrDefault();
|
||||
if (path is null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return Process.GetProcessesByName(ProcessName).Where(process => string.Equals(path.Path, process.MainModule.FileName, StringComparison.Ordinal)).Any();
|
||||
}
|
||||
catch
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return Process.GetProcessesByName(ProcessName).Any();
|
||||
}
|
||||
|
||||
private void ClearGwLocks()
|
||||
{
|
||||
this.SetRegistryGuildwarsPath();
|
||||
foreach (var process in Process.GetProcessesByName(ProcessName))
|
||||
{
|
||||
this.mutexHandler.CloseMutex(process, ArenaNetMutex);
|
||||
}
|
||||
}
|
||||
|
||||
private void SetRegistryGuildwarsPath()
|
||||
{
|
||||
var path = this.configurationManager.GetConfiguration().GuildwarsPaths.Where(path => path.Default).FirstOrDefault();
|
||||
if (path is null)
|
||||
{
|
||||
throw new ExecutableNotFoundException("No executable currently selected");
|
||||
}
|
||||
|
||||
var gamePath = path.Path;
|
||||
try
|
||||
{
|
||||
var registryKey = GetGuildwarsRegistryKey(true);
|
||||
registryKey.SetValue("Path", gamePath);
|
||||
registryKey.SetValue("Src", gamePath);
|
||||
registryKey.Close();
|
||||
}
|
||||
catch (SecurityException ex)
|
||||
{
|
||||
this.logger.LogCritical($"Multi-launch requires administrator rights. Details: {ex}");
|
||||
}
|
||||
}
|
||||
|
||||
private static RegistryKey GetGuildwarsRegistryKey(bool write)
|
||||
{
|
||||
var gwKey = Registry.CurrentUser.OpenSubKey("SOFTWARE")?.OpenSubKey("ArenaNet")?.OpenSubKey("Guild Wars", write);
|
||||
if (gwKey is not null)
|
||||
{
|
||||
return gwKey;
|
||||
}
|
||||
|
||||
gwKey = Registry.CurrentUser.OpenSubKey("SOFTWARE")?.OpenSubKey("WOW6432Node")?.OpenSubKey("ArenaNet")?.OpenSubKey("Guild Wars", write);
|
||||
if (gwKey is not null)
|
||||
{
|
||||
return gwKey;
|
||||
}
|
||||
|
||||
gwKey = Registry.LocalMachine.OpenSubKey("SOFTWARE")?.OpenSubKey("ArenaNet")?.OpenSubKey("Guild Wars", write);
|
||||
if (gwKey is not null)
|
||||
{
|
||||
return gwKey;
|
||||
}
|
||||
|
||||
gwKey = Registry.LocalMachine.OpenSubKey("SOFTWARE")?.OpenSubKey("WOW6432Node")?.OpenSubKey("ArenaNet")?.OpenSubKey("Guild Wars", write);
|
||||
if (gwKey is not null)
|
||||
{
|
||||
return gwKey;
|
||||
}
|
||||
|
||||
throw new InvalidOperationException("Could not find registry key for guildwars.");
|
||||
}
|
||||
|
||||
private static bool GuildwarsToolboxProcessDetected()
|
||||
{
|
||||
return Process.GetProcessesByName(ToolboxProcessName).Any();
|
||||
}
|
||||
|
||||
private static bool TexModProcessDetected()
|
||||
{
|
||||
return Process.GetProcesses()
|
||||
.Where(process => string.Equals(process.ProcessName, UModProcessName, StringComparison.OrdinalIgnoreCase) ||
|
||||
string.Equals(process.ProcessName, TexModProcessName, StringComparison.OrdinalIgnoreCase)).Any();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Daybreak.Services.ApplicationLauncher
|
||||
{
|
||||
public interface IApplicationLauncher
|
||||
{
|
||||
bool IsGuildwarsRunning { get; }
|
||||
bool IsToolboxRunning { get; }
|
||||
bool IsTexmodRunning { get; }
|
||||
Task LaunchGuildwars();
|
||||
Task LaunchGuildwarsToolbox();
|
||||
Task LaunchTexmod();
|
||||
void RestartDaybreakAsAdmin();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,350 @@
|
||||
using Daybreak.Models.Builds;
|
||||
using Daybreak.Services.BuildTemplates.Models;
|
||||
using Daybreak.Services.Logging;
|
||||
using Daybreak.Utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Extensions;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Daybreak.Services.BuildTemplates
|
||||
{
|
||||
public sealed class BuildTemplateManager : IBuildTemplateManager
|
||||
{
|
||||
private const string DecodingLookupTable = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
|
||||
private readonly static string BuildsPath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + "\\Guild Wars\\Templates\\Skills";
|
||||
|
||||
private readonly ILogger logger;
|
||||
|
||||
public BuildTemplateManager(
|
||||
ILogger logger)
|
||||
{
|
||||
this.logger = logger.ThrowIfNull(nameof(logger));
|
||||
}
|
||||
|
||||
public bool IsTemplate(string template)
|
||||
{
|
||||
if (template.IsNullOrWhiteSpace())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (template.Where(c => DecodingLookupTable.Contains(c) is false).Any())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public BuildEntry CreateBuild()
|
||||
{
|
||||
var emptyBuild = new Build();
|
||||
var builds = GetBuilds();
|
||||
var baseName = "New build";
|
||||
var name = baseName;
|
||||
int count = 0;
|
||||
while(builds.Where(b => b.Name.Equals(name, StringComparison.OrdinalIgnoreCase)).Any())
|
||||
{
|
||||
name = baseName + count;
|
||||
count++;
|
||||
}
|
||||
|
||||
var entry = new BuildEntry { Build = emptyBuild, Name = name, PreviousName = string.Empty };
|
||||
this.SaveBuild(entry);
|
||||
return entry;
|
||||
}
|
||||
|
||||
public BuildEntry CreateBuild(string name)
|
||||
{
|
||||
var emptyBuild = new Build();
|
||||
var entry = new BuildEntry { Build = emptyBuild, Name = name, PreviousName = string.Empty };
|
||||
this.SaveBuild(entry);
|
||||
return entry;
|
||||
}
|
||||
|
||||
public void SaveBuild(BuildEntry buildEntry)
|
||||
{
|
||||
var encodedBuild = this.EncodeTemplate(buildEntry.Build);
|
||||
if (string.IsNullOrWhiteSpace(buildEntry.PreviousName))
|
||||
{
|
||||
File.Delete($"{BuildsPath}\\{buildEntry.PreviousName}.txt");
|
||||
}
|
||||
|
||||
File.WriteAllText($"{BuildsPath}\\{buildEntry.Name}.txt", encodedBuild);
|
||||
}
|
||||
|
||||
public void RemoveBuild(BuildEntry buildEntry)
|
||||
{
|
||||
if (File.Exists($"{BuildsPath}\\{buildEntry.Name}.txt"))
|
||||
{
|
||||
File.Delete($"{BuildsPath}\\{buildEntry.Name}.txt");
|
||||
}
|
||||
|
||||
if (File.Exists($"{BuildsPath}\\{buildEntry.PreviousName}.txt"))
|
||||
{
|
||||
File.Delete($"{BuildsPath}\\{buildEntry.PreviousName}.txt");
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerable<BuildEntry> GetBuilds()
|
||||
{
|
||||
foreach (var file in Directory.GetFiles(BuildsPath))
|
||||
{
|
||||
Build build = default;
|
||||
try
|
||||
{
|
||||
build = this.DecodeTemplate(File.ReadAllText(file));
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
this.logger.LogError($"Failed to decode template from file {file}. Details: {e}");
|
||||
}
|
||||
|
||||
if (build is not null)
|
||||
{
|
||||
yield return new BuildEntry { Build = build, Name = Path.GetFileNameWithoutExtension(file), PreviousName = Path.GetFileNameWithoutExtension(file) };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Build DecodeTemplate(string template)
|
||||
{
|
||||
return this.DecodeTemplateInner(template);
|
||||
}
|
||||
|
||||
public string EncodeTemplate(Build build)
|
||||
{
|
||||
return this.EncodeTemplateInner(build);
|
||||
}
|
||||
|
||||
private Build DecodeTemplateInner(string template)
|
||||
{
|
||||
this.logger.LogInformation("Attempting to decode template");
|
||||
var buildMetadata = ParseEncodedTemplate(template);
|
||||
this.logger.LogInformation("Decoded template. Beginning parsing");
|
||||
if (buildMetadata.VersionNumber != 0)
|
||||
{
|
||||
this.logger.LogError($"Expected version number to be 0 but found {buildMetadata.VersionNumber}");
|
||||
throw new InvalidOperationException($"Failed to parse template");
|
||||
}
|
||||
|
||||
var build = new Build()
|
||||
{
|
||||
BuildMetadata = buildMetadata,
|
||||
Skills = new()
|
||||
};
|
||||
|
||||
if (Profession.TryParse(buildMetadata.PrimaryProfessionId, out var primaryProfession) is false)
|
||||
{
|
||||
this.logger.LogError($"Failed to parse profession with id {buildMetadata.PrimaryProfessionId}");
|
||||
throw new InvalidOperationException($"Failed to parse template");
|
||||
}
|
||||
|
||||
build.Primary = primaryProfession;
|
||||
if (Profession.TryParse(buildMetadata.SecondaryProfessionId, out var secondaryProfession) is false)
|
||||
{
|
||||
this.logger.LogError($"Failed to parse profession with id {buildMetadata.SecondaryProfessionId}");
|
||||
throw new InvalidOperationException($"Failed to parse template");
|
||||
}
|
||||
|
||||
build.Secondary = secondaryProfession;
|
||||
for(int i = 0; i < buildMetadata.AttributeCount; i++)
|
||||
{
|
||||
if (Daybreak.Models.Builds.Attribute.TryParse(buildMetadata.AttributesIds[i], out var attribute) is false)
|
||||
{
|
||||
this.logger.LogError($"Failed to parse attribute with id {buildMetadata.AttributesIds[i]}");
|
||||
throw new InvalidOperationException($"Failed to parse template");
|
||||
}
|
||||
|
||||
build.Attributes.Add(new AttributeEntry { Attribute = attribute, Points = buildMetadata.AttributePoints[i] });
|
||||
}
|
||||
|
||||
for(int i = 0; i < 8; i++)
|
||||
{
|
||||
if (Skill.TryParse(buildMetadata.SkillIds[i], out var skill) is false)
|
||||
{
|
||||
this.logger.LogError($"Failed to parse skill with id {buildMetadata.SkillIds[i]}");
|
||||
throw new InvalidOperationException($"Failed to parse template");
|
||||
}
|
||||
|
||||
build.Skills.Add(skill);
|
||||
}
|
||||
|
||||
return build;
|
||||
}
|
||||
|
||||
private string EncodeTemplateInner(Build build)
|
||||
{
|
||||
this.logger.LogInformation("Building build metadata");
|
||||
var buildMetadata = new BuildMetadata
|
||||
{
|
||||
VersionNumber = 0,
|
||||
NewTemplate = true,
|
||||
Header = 14,
|
||||
PrimaryProfessionId = build.Primary.Id,
|
||||
SecondaryProfessionId = build.Secondary.Id,
|
||||
AttributeCount = build.Attributes.Count,
|
||||
AttributesIds = build.Attributes.Select(attrEntry => attrEntry.Attribute.Id).ToList(),
|
||||
AttributePoints = build.Attributes.Select(attrEntry => attrEntry.Points).ToList(),
|
||||
SkillIds = build.Skills.Select(skill => skill.Id).ToList(),
|
||||
TailPresent = true
|
||||
};
|
||||
|
||||
this.logger.LogInformation("Encoding metadata into binary");
|
||||
var encodedBinary = BuildEncodedString(buildMetadata);
|
||||
int index = 0;
|
||||
var encodedBase64 = new List<int>();
|
||||
while (index < encodedBinary.Length)
|
||||
{
|
||||
var subset = new string(encodedBinary.Skip(index).Take(6).ToArray());
|
||||
encodedBase64.Add(FromBitString(subset));
|
||||
index += 6;
|
||||
}
|
||||
|
||||
var template = new string(encodedBase64.Select(b => DecodingLookupTable[b]).ToArray());
|
||||
return template;
|
||||
}
|
||||
|
||||
private static string ToBitString(int value)
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
while(value > 0)
|
||||
{
|
||||
sb.Append(value % 2 == 1 ? 1 : 0);
|
||||
value /= 2;
|
||||
}
|
||||
|
||||
while(sb.Length < 6)
|
||||
{
|
||||
sb.Append(0);
|
||||
}
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
private static BuildMetadata ParseEncodedTemplate(string template)
|
||||
{
|
||||
var curedTemplate = template.Trim();
|
||||
|
||||
var buildMetadata = new BuildMetadata();
|
||||
buildMetadata.Base64Decoded = template.Select(c => DecodingLookupTable.IndexOf(c)).ToList();
|
||||
buildMetadata.BinaryDecoded = buildMetadata.Base64Decoded.Select(b => ToBitString(b)).ToList();
|
||||
|
||||
var stream = new DecodeCharStream(buildMetadata.BinaryDecoded.ToArray());
|
||||
buildMetadata.Header = stream.Read(4);
|
||||
if (buildMetadata.Header == 14)
|
||||
{
|
||||
buildMetadata.VersionNumber = stream.Read(4);
|
||||
buildMetadata.NewTemplate = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
buildMetadata.VersionNumber = buildMetadata.Header;
|
||||
buildMetadata.NewTemplate = false;
|
||||
}
|
||||
|
||||
buildMetadata.ProfessionIdLength = stream.Read(2) * 2 + 4;
|
||||
buildMetadata.PrimaryProfessionId = stream.Read(buildMetadata.ProfessionIdLength);
|
||||
buildMetadata.SecondaryProfessionId = stream.Read(buildMetadata.ProfessionIdLength);
|
||||
buildMetadata.AttributeCount = stream.Read(4);
|
||||
buildMetadata.AttributesLength = stream.Read(4) + 4;
|
||||
for (int i = 0; i < buildMetadata.AttributeCount; i++)
|
||||
{
|
||||
buildMetadata.AttributesIds.Add(stream.Read(buildMetadata.AttributesLength));
|
||||
buildMetadata.AttributePoints.Add(stream.Read(4));
|
||||
}
|
||||
|
||||
buildMetadata.SkillsLength = stream.Read(4) + 8;
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
buildMetadata.SkillIds.Add(stream.Read(buildMetadata.SkillsLength));
|
||||
}
|
||||
|
||||
if (stream.Position < stream.Length - 1)
|
||||
{
|
||||
buildMetadata.TailPresent = true;
|
||||
}
|
||||
|
||||
return buildMetadata;
|
||||
}
|
||||
|
||||
private static string BuildEncodedString(BuildMetadata buildMetadata)
|
||||
{
|
||||
var stream = new EncodeCharStream();
|
||||
if(buildMetadata.NewTemplate || buildMetadata.Header == 14)
|
||||
{
|
||||
stream.Write(14, 4);
|
||||
}
|
||||
|
||||
stream.Write(0, 4);
|
||||
|
||||
var desiredProfessionIdLength = GetBitLength(new List<int> { buildMetadata.PrimaryProfessionId, buildMetadata.SecondaryProfessionId }.Max());
|
||||
var professionIdLength = Math.Max((desiredProfessionIdLength - 4) / 2, 0);
|
||||
var finalProfessionIdLength = professionIdLength * 2 + 4;
|
||||
stream.Write(professionIdLength, 2);
|
||||
stream.Write(buildMetadata.PrimaryProfessionId, finalProfessionIdLength);
|
||||
stream.Write(buildMetadata.SecondaryProfessionId, finalProfessionIdLength);
|
||||
|
||||
stream.Write(buildMetadata.AttributeCount, 4);
|
||||
var desiredAttributesLength = GetBitLength(buildMetadata.AttributesIds.Any() ? buildMetadata.AttributesIds.Max() : 0);
|
||||
var attributesLength = Math.Max(desiredAttributesLength - 4, 0);
|
||||
var finalAttributesLength = attributesLength + 4;
|
||||
stream.Write(attributesLength, 4);
|
||||
for(int i = 0; i < buildMetadata.AttributeCount; i++)
|
||||
{
|
||||
stream.Write(buildMetadata.AttributesIds[i], finalAttributesLength);
|
||||
stream.Write(buildMetadata.AttributePoints[i], 4);
|
||||
}
|
||||
|
||||
var desiredSkillsLength = GetBitLength(buildMetadata.SkillIds.Max());
|
||||
var skillsLength = Math.Max(desiredSkillsLength - 8, 0);
|
||||
var finalSkillsLength = skillsLength + 8;
|
||||
stream.Write(skillsLength, 4);
|
||||
for(int i = 0; i < 8; i++)
|
||||
{
|
||||
stream.Write(buildMetadata.SkillIds[i], finalSkillsLength);
|
||||
}
|
||||
|
||||
if (buildMetadata.TailPresent)
|
||||
{
|
||||
stream.Write(0, 1);
|
||||
}
|
||||
|
||||
return stream.GetEncodedString();
|
||||
}
|
||||
|
||||
private static int GetBitLength(int value)
|
||||
{
|
||||
int decimals = 1;
|
||||
value /= 2;
|
||||
while (value > 0)
|
||||
{
|
||||
decimals++;
|
||||
value /= 2;
|
||||
}
|
||||
|
||||
return decimals;
|
||||
}
|
||||
|
||||
private static int FromBitString(string bitString)
|
||||
{
|
||||
var sb = new StringBuilder(bitString);
|
||||
while (sb.Length < 6)
|
||||
{
|
||||
sb.Append('0');
|
||||
}
|
||||
|
||||
bitString = sb.ToString();
|
||||
var value = 0d;
|
||||
for (int i = 0; i < bitString.Length; i++)
|
||||
{
|
||||
value += bitString[i] == '1' ? Math.Pow(2, i) : 0;
|
||||
}
|
||||
|
||||
return (int)value;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
using Daybreak.Models.Builds;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Daybreak.Services.BuildTemplates
|
||||
{
|
||||
public interface IBuildTemplateManager
|
||||
{
|
||||
bool IsTemplate(string template);
|
||||
BuildEntry CreateBuild();
|
||||
BuildEntry CreateBuild(string name);
|
||||
void SaveBuild(BuildEntry buildEntry);
|
||||
void RemoveBuild(BuildEntry buildEntry);
|
||||
IEnumerable<BuildEntry> GetBuilds();
|
||||
Build DecodeTemplate(string template);
|
||||
string EncodeTemplate(Build build);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
using System;
|
||||
|
||||
namespace Daybreak.Services.BuildTemplates.Models
|
||||
{
|
||||
public sealed class DecodeCharStream
|
||||
{
|
||||
private readonly string innerCharArray;
|
||||
|
||||
public int Length => this.innerCharArray.Length;
|
||||
|
||||
public int Position { get; set; }
|
||||
|
||||
public DecodeCharStream(string[] encodedValues)
|
||||
{
|
||||
this.innerCharArray = string.Join("", encodedValues);
|
||||
}
|
||||
|
||||
public int Read(int count)
|
||||
{
|
||||
var value = FromEncodedBinary(this.innerCharArray, this.Position, count);
|
||||
this.Position += count;
|
||||
return value;
|
||||
}
|
||||
|
||||
private static int FromEncodedBinary(string encoded, int startIndex, int count)
|
||||
{
|
||||
var sum = 0d;
|
||||
for (int i = startIndex; i < startIndex + count; i++)
|
||||
{
|
||||
sum += encoded[i] == '1' ? Math.Pow(2, i - startIndex) : 0;
|
||||
}
|
||||
|
||||
return (int)sum;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
using System.Text;
|
||||
|
||||
namespace Daybreak.Services.BuildTemplates.Models
|
||||
{
|
||||
public sealed class EncodeCharStream
|
||||
{
|
||||
private readonly StringBuilder innerStringBuilder = new StringBuilder();
|
||||
|
||||
public void Write(int value, int count)
|
||||
{
|
||||
this.EncodeToBinary(value, count);
|
||||
}
|
||||
|
||||
public string GetEncodedString()
|
||||
{
|
||||
return innerStringBuilder.ToString();
|
||||
}
|
||||
|
||||
private void EncodeToBinary(int value, int count)
|
||||
{
|
||||
while(value > 0 && count > 0)
|
||||
{
|
||||
this.innerStringBuilder.Append(value % 2 == 1 ? '1' : '0');
|
||||
value /= 2;
|
||||
count--;
|
||||
}
|
||||
|
||||
while (count > 0)
|
||||
{
|
||||
this.innerStringBuilder.Append('0');
|
||||
count--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,9 @@
|
||||
using Daybreak.Configuration;
|
||||
using Daybreak.Exceptions;
|
||||
using Daybreak.Services.Logging;
|
||||
using Daybreak.Utils;
|
||||
using System;
|
||||
using System.Extensions;
|
||||
using System.IO;
|
||||
|
||||
namespace Daybreak.Services.Configuration
|
||||
@@ -11,9 +13,11 @@ namespace Daybreak.Services.Configuration
|
||||
private const string ConfigName = "Daybreak.config.json";
|
||||
|
||||
private ApplicationConfiguration applicationConfiguration;
|
||||
private readonly ILogger logger;
|
||||
|
||||
public ConfigurationManager()
|
||||
public ConfigurationManager(ILogger logger)
|
||||
{
|
||||
this.logger = logger.ThrowIfNull(nameof(logger));
|
||||
try
|
||||
{
|
||||
var serializedConfig = File.ReadAllText(ConfigName);
|
||||
@@ -21,7 +25,8 @@ namespace Daybreak.Services.Configuration
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
throw new FatalException("Failed to load application configuration. See inner exception for details", e);
|
||||
this.logger.LogWarning($"No configuration detected. Loading default configuration. Details: {e}");
|
||||
this.applicationConfiguration = new ApplicationConfiguration();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,9 +3,12 @@ using Daybreak.Services.Configuration;
|
||||
using Daybreak.Services.Logging;
|
||||
using Daybreak.Utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Extensions;
|
||||
using System.Linq;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Daybreak.Services.Credentials
|
||||
{
|
||||
@@ -23,43 +26,123 @@ namespace Daybreak.Services.Credentials
|
||||
this.logger = logger.ThrowIfNull(nameof(logger));
|
||||
}
|
||||
|
||||
public Optional<LoginCredentials> GetCredentials()
|
||||
public Task<Optional<LoginCredentials>> GetDefaultCredentials()
|
||||
{
|
||||
this.logger.LogInformation("Retrieving credentials");
|
||||
var config = this.configurationManager.GetConfiguration();
|
||||
if (string.IsNullOrEmpty(config.ProtectedUsername) ||
|
||||
string.IsNullOrEmpty(config.ProtectedPassword))
|
||||
return Task.Run(async () =>
|
||||
{
|
||||
this.logger.LogInformation("No credentials found");
|
||||
return Optional.None<LoginCredentials>();
|
||||
}
|
||||
this.logger.LogInformation("Retrieving default credentials");
|
||||
var defaultCredentials = (await this.GetCredentialList())
|
||||
.Where(creds => creds.Default)
|
||||
.ToList();
|
||||
if (defaultCredentials.Count == 0)
|
||||
{
|
||||
this.logger.LogWarning("No default credentials");
|
||||
return Optional.None<LoginCredentials>();
|
||||
}
|
||||
|
||||
if (defaultCredentials.Count > 1)
|
||||
{
|
||||
this.logger.LogError("Multiple credentials set as default");
|
||||
return Optional.None<LoginCredentials>();
|
||||
}
|
||||
|
||||
return defaultCredentials.FirstOrDefault();
|
||||
});
|
||||
}
|
||||
public Task<List<LoginCredentials>> GetCredentialList()
|
||||
{
|
||||
return Task.Run(() =>
|
||||
{
|
||||
this.logger.LogInformation("Retrieving credentials");
|
||||
var config = this.configurationManager.GetConfiguration();
|
||||
if (config.ProtectedLoginCredentials is null || config.ProtectedLoginCredentials.Count == 0)
|
||||
{
|
||||
this.logger.LogInformation("No credentials found");
|
||||
return new List<LoginCredentials>();
|
||||
}
|
||||
|
||||
return config
|
||||
.ProtectedLoginCredentials
|
||||
.Select(UnprotectCredentials)
|
||||
.Where(CredentialsUnprotected)
|
||||
.Select(ExtractCredentials)
|
||||
.ToList();
|
||||
});
|
||||
}
|
||||
public Task StoreCredentials(List<LoginCredentials> loginCredentials)
|
||||
{
|
||||
return Task.Run(() =>
|
||||
{
|
||||
this.logger.LogInformation("Storing credentials");
|
||||
var config = this.configurationManager.GetConfiguration();
|
||||
config.ProtectedLoginCredentials = loginCredentials
|
||||
.Select(ProtectCredentials)
|
||||
.Where(CredentialsProtected)
|
||||
.Select(ExtractProtectedCredentials)
|
||||
.ToList();
|
||||
this.configurationManager.SaveConfiguration(config);
|
||||
});
|
||||
}
|
||||
|
||||
private Optional<LoginCredentials> UnprotectCredentials(ProtectedLoginCredentials protectedLoginCredentials)
|
||||
{
|
||||
try
|
||||
{
|
||||
var usrbytes = Convert.FromBase64String(config.ProtectedUsername);
|
||||
var psdBytes = Convert.FromBase64String(config.ProtectedPassword);
|
||||
var usrbytes = Convert.FromBase64String(protectedLoginCredentials.ProtectedUsername);
|
||||
var psdBytes = Convert.FromBase64String(protectedLoginCredentials.ProtectedPassword);
|
||||
return new LoginCredentials
|
||||
{
|
||||
Username = Encoding.UTF8.GetString(ProtectedData.Unprotect(usrbytes, Entropy, DataProtectionScope.LocalMachine)),
|
||||
Password = Encoding.UTF8.GetString(ProtectedData.Unprotect(psdBytes, Entropy, DataProtectionScope.LocalMachine))
|
||||
Password = Encoding.UTF8.GetString(ProtectedData.Unprotect(psdBytes, Entropy, DataProtectionScope.LocalMachine)),
|
||||
CharacterName = protectedLoginCredentials.CharacterName,
|
||||
Default = protectedLoginCredentials.Default
|
||||
};
|
||||
}
|
||||
catch(Exception e)
|
||||
catch (Exception e)
|
||||
{
|
||||
this.logger.LogError($"Unable to retrieve credentials. Details: {e}");
|
||||
return Optional.None<LoginCredentials>();
|
||||
}
|
||||
}
|
||||
|
||||
public void StoreCredentials(LoginCredentials loginCredentials)
|
||||
private Optional<ProtectedLoginCredentials> ProtectCredentials(LoginCredentials loginCredentials)
|
||||
{
|
||||
this.logger.LogInformation("Storing credentials");
|
||||
var usrBytes = Encoding.UTF8.GetBytes(loginCredentials.Username);
|
||||
var psdBytes = Encoding.UTF8.GetBytes(loginCredentials.Password);
|
||||
var config = this.configurationManager.GetConfiguration();
|
||||
config.ProtectedUsername = Convert.ToBase64String(ProtectedData.Protect(usrBytes, Entropy, DataProtectionScope.LocalMachine));
|
||||
config.ProtectedPassword = Convert.ToBase64String(ProtectedData.Protect(psdBytes, Entropy, DataProtectionScope.LocalMachine));
|
||||
this.configurationManager.SaveConfiguration(config);
|
||||
try
|
||||
{
|
||||
var usrBytes = Encoding.UTF8.GetBytes(loginCredentials.Username);
|
||||
var psdBytes = Encoding.UTF8.GetBytes(loginCredentials.Password);
|
||||
return new ProtectedLoginCredentials
|
||||
{
|
||||
ProtectedUsername = Convert.ToBase64String(ProtectedData.Protect(usrBytes, Entropy, DataProtectionScope.LocalMachine)),
|
||||
ProtectedPassword = Convert.ToBase64String(ProtectedData.Protect(psdBytes, Entropy, DataProtectionScope.LocalMachine)),
|
||||
CharacterName = loginCredentials.CharacterName,
|
||||
Default = loginCredentials.Default
|
||||
};
|
||||
}
|
||||
catch
|
||||
{
|
||||
return Optional.None<ProtectedLoginCredentials>();
|
||||
}
|
||||
}
|
||||
|
||||
private bool CredentialsUnprotected(Optional<LoginCredentials> optional)
|
||||
{
|
||||
return optional
|
||||
.Switch(onSome: _ => true, onNone: () => false)
|
||||
.ExtractValue();
|
||||
}
|
||||
private bool CredentialsProtected(Optional<ProtectedLoginCredentials> optional)
|
||||
{
|
||||
return optional
|
||||
.Switch(onSome: _ => true, onNone: () => false)
|
||||
.ExtractValue();
|
||||
}
|
||||
private ProtectedLoginCredentials ExtractProtectedCredentials(Optional<ProtectedLoginCredentials> optional)
|
||||
{
|
||||
return optional.ExtractValue();
|
||||
}
|
||||
private LoginCredentials ExtractCredentials(Optional<LoginCredentials> optional)
|
||||
{
|
||||
return optional.ExtractValue();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
using Daybreak.Models;
|
||||
using System.Collections.Generic;
|
||||
using System.Extensions;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Daybreak.Services.Credentials
|
||||
{
|
||||
public interface ICredentialManager
|
||||
{
|
||||
void StoreCredentials(LoginCredentials loginCredentials);
|
||||
Optional<LoginCredentials> GetCredentials();
|
||||
Task StoreCredentials(List<LoginCredentials> loginCredentials);
|
||||
Task<List<LoginCredentials>> GetCredentialList();
|
||||
Task<Optional<LoginCredentials>> GetDefaultCredentials();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
using Daybreak.Models.Builds;
|
||||
using System.Extensions;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Daybreak.Services.IconRetrieve
|
||||
{
|
||||
public interface IIconRetriever
|
||||
{
|
||||
Task<Optional<Stream>> GetIcon(Skill skill);
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user