From 2d3138bf60e47a467a88c8ca3a342f039242af65 Mon Sep 17 00:00:00 2001
From: heftymouse <59918974+heftymouse@users.noreply.github.com>
Date: Thu, 6 Jun 2024 03:50:38 +0530
Subject: [PATCH 01/11] composition progress graph
---
src/Files.App/Files.App.csproj | 5 +-
.../UserControls/AddressToolbar.xaml | 3 +-
.../UserControls/StatusCenter/SpeedGraph.xaml | 15 ++
.../StatusCenter/SpeedGraph.xaml.cs | 126 ++++++++++++++
.../{ => StatusCenter}/StatusCenter.xaml | 30 +---
.../{ => StatusCenter}/StatusCenter.xaml.cs | 2 +-
.../Utils/StatusCenter/StatusCenterItem.cs | 157 ++----------------
7 files changed, 161 insertions(+), 177 deletions(-)
create mode 100644 src/Files.App/UserControls/StatusCenter/SpeedGraph.xaml
create mode 100644 src/Files.App/UserControls/StatusCenter/SpeedGraph.xaml.cs
rename src/Files.App/UserControls/{ => StatusCenter}/StatusCenter.xaml (92%)
rename src/Files.App/UserControls/{ => StatusCenter}/StatusCenter.xaml.cs (96%)
diff --git a/src/Files.App/Files.App.csproj b/src/Files.App/Files.App.csproj
index e181346644b6..7ebcd2ab9298 100644
--- a/src/Files.App/Files.App.csproj
+++ b/src/Files.App/Files.App.csproj
@@ -39,7 +39,7 @@
TRACE;RELEASE;NETFX_CORE;DISABLE_XAML_GENERATED_MAIN
true
-
+
@@ -74,7 +74,6 @@
-
@@ -140,5 +139,5 @@
-
+
diff --git a/src/Files.App/UserControls/AddressToolbar.xaml b/src/Files.App/UserControls/AddressToolbar.xaml
index c7abdff6b60d..c7cfd048a082 100644
--- a/src/Files.App/UserControls/AddressToolbar.xaml
+++ b/src/Files.App/UserControls/AddressToolbar.xaml
@@ -16,6 +16,7 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:triggers="using:CommunityToolkit.WinUI.UI.Triggers"
xmlns:uc="using:Files.App.UserControls"
+ xmlns:ucs="using:Files.App.UserControls.StatusCenter"
x:Name="NavToolbar"
Height="50"
d:DesignHeight="50"
@@ -481,7 +482,7 @@
-
+
+
+
+
diff --git a/src/Files.App/UserControls/StatusCenter/SpeedGraph.xaml.cs b/src/Files.App/UserControls/StatusCenter/SpeedGraph.xaml.cs
new file mode 100644
index 000000000000..dd435af96fc4
--- /dev/null
+++ b/src/Files.App/UserControls/StatusCenter/SpeedGraph.xaml.cs
@@ -0,0 +1,126 @@
+using Microsoft.Graphics.Canvas.Geometry;
+using Microsoft.UI;
+using Microsoft.UI.Composition;
+using Microsoft.UI.Xaml;
+using Microsoft.UI.Xaml.Controls;
+using Microsoft.UI.Xaml.Hosting;
+using System.Collections.Specialized;
+using System.Numerics;
+using Windows.UI;
+
+// To learn more about WinUI, the WinUI project structure,
+// and more about our project templates, see: http://aka.ms/winui-project-info.
+
+namespace Files.App.UserControls.StatusCenter
+{
+ public sealed partial class SpeedGraph : UserControl
+ {
+ public ObservableCollection Points
+ {
+ get => (ObservableCollection)GetValue(PointsProperty);
+ set
+ {
+ highestValue = 0;
+ SetValue(PointsProperty, value);
+ }
+ }
+
+ public static readonly DependencyProperty PointsProperty =
+ DependencyProperty.Register(nameof(Points), typeof(ObservableCollection), typeof(SpeedGraph), null);
+
+ Compositor compositor;
+ ContainerVisual rootVisual;
+ ShapeVisual graphVisual;
+ CompositionSpriteShape graphShape;
+ InsetClip graphClip;
+
+ float width;
+ float height;
+
+ float highestValue;
+
+ public SpeedGraph()
+ {
+ this.InitializeComponent();
+ }
+
+ private void UserControl_Loaded(object sender, RoutedEventArgs e)
+ {
+ // is it a bad idea to recreate these on every load?
+ // TODO: it doesn't work the first time you open the flyout
+ rootVisual = (ContainerVisual)ElementCompositionPreview.GetElementVisual(graphRoot);
+ compositor = rootVisual.Compositor;
+
+ width = rootVisual.Size.X;
+ height = rootVisual.Size.Y;
+
+ var bgVisual = compositor.CreateSpriteVisual();
+ bgVisual.Size = rootVisual.Size;
+ bgVisual.Brush = compositor.CreateColorBrush(Color.FromArgb(0x20, 0x40, 0xE0, 0xD0));
+ rootVisual.Children.InsertAtBottom(bgVisual);
+
+ graphVisual = compositor.CreateShapeVisual();
+ graphVisual.Size = rootVisual.Size;
+ rootVisual.Children.InsertAtBottom(graphVisual);
+
+ graphShape = compositor.CreateSpriteShape();
+ // TODO: use accent theme resources
+ graphShape.FillBrush = compositor.CreateColorBrush(Colors.Transparent);
+ graphShape.StrokeBrush = compositor.CreateColorBrush(Colors.Turquoise);
+ graphVisual.Shapes.Add(graphShape);
+
+ graphClip = compositor.CreateInsetClip();
+ graphClip.RightInset = width;
+ rootVisual.Clip = graphClip;
+
+ //// if it gets unloaded and reloaded because of the flyout closing
+ //if (Points.Count > 1)
+ UpdateGraph();
+
+ Points.CollectionChanged += PointsChanged;
+ }
+
+ private void UserControl_Unloaded(object sender, RoutedEventArgs e)
+ {
+ rootVisual.Children.RemoveAll();
+ graphVisual = null!;
+ graphShape = null!;
+ graphClip = null!;
+ Points.CollectionChanged -= PointsChanged;
+ }
+
+ private void PointsChanged(object? sender, NotifyCollectionChangedEventArgs e)
+ {
+ if (e.Action != NotifyCollectionChangedAction.Add)
+ return;
+
+ if (Points[^1].Y > highestValue)
+ highestValue = Points[^1].Y;
+
+ UpdateGraph();
+ }
+
+ void UpdateGraph()
+ {
+ var geometry = CreatePathFromPoints();
+ graphShape.Geometry = geometry;
+ graphClip.RightInset = width - (width * Points[^1].X / 100f) + 1;
+ }
+
+ CompositionPathGeometry CreatePathFromPoints()
+ {
+ using var pathBuilder = new CanvasPathBuilder(null);
+ pathBuilder.BeginFigure(0f, height);
+ for (int i = 0; i < Points.Count; i++)
+ {
+ // no smooth curve for now. a little ugly but maybe for the best performance-wise, we'll see before this gets merged
+ pathBuilder.AddLine(width * Points[i].X / 100f, height - (Points[i].Y / highestValue) * (height * 0.9f));
+ }
+ pathBuilder.AddLine(width * Points[^1].X / 100f, height);
+ pathBuilder.EndFigure(CanvasFigureLoop.Closed);
+ var geometry = compositor.CreatePathGeometry();
+ geometry.Path = new CompositionPath(CanvasGeometry.CreatePath(pathBuilder));
+ return geometry;
+ }
+ }
+}
diff --git a/src/Files.App/UserControls/StatusCenter.xaml b/src/Files.App/UserControls/StatusCenter/StatusCenter.xaml
similarity index 92%
rename from src/Files.App/UserControls/StatusCenter.xaml
rename to src/Files.App/UserControls/StatusCenter/StatusCenter.xaml
index be5bb95e16a8..b9f194ff05db 100644
--- a/src/Files.App/UserControls/StatusCenter.xaml
+++ b/src/Files.App/UserControls/StatusCenter/StatusCenter.xaml
@@ -1,12 +1,12 @@
@@ -227,7 +227,7 @@
-
-
-
-
-
-
-
+
diff --git a/src/Files.App/UserControls/StatusCenter.xaml.cs b/src/Files.App/UserControls/StatusCenter/StatusCenter.xaml.cs
similarity index 96%
rename from src/Files.App/UserControls/StatusCenter.xaml.cs
rename to src/Files.App/UserControls/StatusCenter/StatusCenter.xaml.cs
index c54df0caaad1..c8904dad330f 100644
--- a/src/Files.App/UserControls/StatusCenter.xaml.cs
+++ b/src/Files.App/UserControls/StatusCenter/StatusCenter.xaml.cs
@@ -5,7 +5,7 @@
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
-namespace Files.App.UserControls
+namespace Files.App.UserControls.StatusCenter
{
public sealed partial class StatusCenter : UserControl
{
diff --git a/src/Files.App/Utils/StatusCenter/StatusCenterItem.cs b/src/Files.App/Utils/StatusCenter/StatusCenterItem.cs
index ee5c871942a3..b60b68177c5e 100644
--- a/src/Files.App/Utils/StatusCenter/StatusCenterItem.cs
+++ b/src/Files.App/Utils/StatusCenter/StatusCenterItem.cs
@@ -2,14 +2,8 @@
// Licensed under the MIT License. See the LICENSE.
using System.Windows.Input;
-using SkiaSharp;
-using LiveChartsCore;
-using LiveChartsCore.Drawing;
-using LiveChartsCore.Kernel.Sketches;
-using LiveChartsCore.SkiaSharpView;
-using LiveChartsCore.SkiaSharpView.Painting;
-using LiveChartsCore.Defaults;
using Microsoft.UI.Xaml.Media;
+using System.Numerics;
namespace Files.App.Utils.StatusCenter
{
@@ -161,22 +155,6 @@ public StatusCenterItemProgressModel Progress
public string? SubHeaderStringResource { get; private set; }
- public ObservableCollection? SpeedGraphValues { get; private set; }
-
- public ObservableCollection? SpeedGraphBackgroundValues { get; private set; }
-
- public ObservableCollection? SpeedGraphSeries { get; private set; }
-
- public ObservableCollection? SpeedGraphBackgroundSeries { get; private set; }
-
- public ObservableCollection? SpeedGraphXAxes { get; private set; }
-
- public ObservableCollection? SpeedGraphYAxes { get; private set; }
-
- public ObservableCollection? SpeedGraphBackgroundXAxes { get; private set; }
-
- public ObservableCollection? SpeedGraphBackgroundYAxes { get; private set; }
-
public double IconBackgroundCircleBorderOpacity { get; private set; }
public CancellationToken CancellationToken
@@ -189,6 +167,8 @@ public string? HeaderTooltip
private readonly CancellationTokenSource? _operationCancellationToken;
+ public readonly ObservableCollection SpeedGraphValues;
+
public ICommand CancelCommand { get; }
public StatusCenterItem(
@@ -218,7 +198,6 @@ public StatusCenterItem(
IconBackgroundCircleBorderOpacity = 1;
AnimatedIconState = "NormalOff";
SpeedGraphValues = [];
- SpeedGraphBackgroundValues = [];
CancelCommand = new RelayCommand(ExecuteCancelCommand);
Message = "ProcessingItems".GetLocalizedResource();
Source = source;
@@ -228,108 +207,6 @@ public StatusCenterItem(
if (App.Current.Resources["App.Theme.FillColorAttentionBrush"] is not SolidColorBrush accentBrush)
return;
- // Initialize graph background fill series
- SpeedGraphBackgroundSeries =
- [
- new LineSeries
- {
- Values = SpeedGraphBackgroundValues,
- GeometrySize = 0d,
- DataPadding = new(0, 0),
- IsHoverable = false,
-
- // Stroke
- Stroke = new SolidColorPaint(
- new(accentBrush.Color.R, accentBrush.Color.G, accentBrush.Color.B, 40),
- 0.1f),
-
- // Fill under the stroke
- Fill = new LinearGradientPaint(
- [
- new(accentBrush.Color.R, accentBrush.Color.G, accentBrush.Color.B, 40)
- ],
- new(0f, 0f),
- new(0f, 0f)),
- }
- ];
-
- // Initialize graph series
- SpeedGraphSeries =
- [
- new LineSeries
- {
- Values = SpeedGraphValues,
- GeometrySize = 0d,
- DataPadding = new(0, 0),
- IsHoverable = false,
-
- // Stroke
- Stroke = new SolidColorPaint(
- new(accentBrush.Color.R, accentBrush.Color.G, accentBrush.Color.B),
- 1f),
-
- // Fill under the stroke
- Fill = new LinearGradientPaint(
- [
- new(accentBrush.Color.R, accentBrush.Color.G, accentBrush.Color.B, 50),
- new(accentBrush.Color.R, accentBrush.Color.G, accentBrush.Color.B, 10)
- ],
- new(0f, 0f),
- new(0f, 0f),
- [0.1f, 1.0f]),
- },
- ];
-
- // Initialize X axes of the graph background fill
- SpeedGraphBackgroundXAxes =
- [
- new Axis
- {
- Padding = new Padding(0, 0),
- Labels = new List(),
- MaxLimit = 100,
- ShowSeparatorLines = false,
- }
- ];
-
- // Initialize X axes of the graph
- SpeedGraphXAxes =
- [
- new Axis
- {
- Padding = new Padding(0, 0),
- Labels = new List(),
- MaxLimit = 100,
- ShowSeparatorLines = false,
- }
- ];
-
- // Initialize Y axes of the graph background fill
- SpeedGraphBackgroundYAxes =
- [
- new Axis
- {
- Padding = new Padding(0, 0),
- Labels = new List(),
- ShowSeparatorLines = false,
- MaxLimit = 100,
- }
- ];
-
- // Initialize Y axes of the graph
- SpeedGraphYAxes =
- [
- new Axis
- {
- Padding = new Padding(0, 0),
- Labels = new List(),
- ShowSeparatorLines = false,
- }
- ];
-
- SpeedGraphXAxes[0].SharedWith = SpeedGraphBackgroundXAxes;
- SpeedGraphBackgroundXAxes[0].SharedWith = SpeedGraphXAxes;
-
// Set icon and initialize string resources
switch (FileSystemOperationReturnResult)
{
@@ -450,7 +327,7 @@ private void ReportProgress(StatusCenterItemProgressModel value)
OnPropertyChanged(nameof(HeaderTooltip));
// Graph item point
- ObservablePoint point;
+ Vector2 point;
// Set speed text and percentage
switch (value.TotalSize, value.ItemsCount)
@@ -461,7 +338,7 @@ private void ReportProgress(StatusCenterItemProgressModel value)
SpeedText = $"{value.ProcessingSizeSpeed.ToSizeString()}/s";
- point = new(value.ProcessedSize * 100.0 / value.TotalSize, value.ProcessingSizeSpeed);
+ point = new((float)(value.ProcessedSize * 100.0 / value.TotalSize), (float)value.ProcessingSizeSpeed);
break;
// In progress, displaying processed size
@@ -470,7 +347,7 @@ private void ReportProgress(StatusCenterItemProgressModel value)
SpeedText = $"{value.ProcessingSizeSpeed.ToSizeString()}/s";
- point = new(value.ProcessedSize * 100.0 / value.TotalSize, value.ProcessingSizeSpeed);
+ point = new((float)(value.ProcessedSize * 100.0 / value.TotalSize), (float)value.ProcessingSizeSpeed);
break;
// In progress, displaying items count
@@ -479,11 +356,11 @@ private void ReportProgress(StatusCenterItemProgressModel value)
SpeedText = $"{value.ProcessingItemsCountSpeed:0} items/s";
- point = new(value.ProcessedItemsCount * 100.0 / value.ItemsCount, value.ProcessingItemsCountSpeed);
+ point = new((float)(value.ProcessedItemsCount * 100.0 / value.ItemsCount), (float)value.ProcessingItemsCountSpeed);
break;
default:
- point = new(ProgressPercentage, value.ProcessingItemsCountSpeed);
+ point = new(ProgressPercentage, (float)value.ProcessingItemsCountSpeed);
SpeedText = (value.ProcessedSize, value.ProcessedItemsCount) switch
{
@@ -497,22 +374,10 @@ private void ReportProgress(StatusCenterItemProgressModel value)
bool isSamePoint = false;
- // Remove the point that has the same X position
- if (SpeedGraphValues?.FirstOrDefault(v => v.X == point.X) is ObservablePoint existingPoint)
- {
- SpeedGraphValues.Remove(existingPoint);
- isSamePoint = true;
- }
-
- // Add a new background fill point
- if (!isSamePoint)
- {
- ObservablePoint newPoint = new(point.X, 100);
- SpeedGraphBackgroundValues?.Add(newPoint);
- }
-
// Add a new point
- SpeedGraphValues?.Add(point);
+ // 'debounce' updates a bit so the graph isn't too noisy
+ if (SpeedGraphValues.Count == 0 || (point.X - SpeedGraphValues[^1].X) > 0.5)
+ SpeedGraphValues?.Add(point);
// Add percentage to the header
if (!IsIndeterminateProgress)
From 3ef0f1616abf53a2291d5520e5a2f996cccb2fb7 Mon Sep 17 00:00:00 2001
From: heftymouse <59918974+heftymouse@users.noreply.github.com>
Date: Thu, 6 Jun 2024 14:51:02 +0530
Subject: [PATCH 02/11] code that maybe works occassionally
---
.../UserControls/StatusCenter/SpeedGraph.xaml | 5 +-
.../StatusCenter/SpeedGraph.xaml.cs | 72 +++++++++++++------
2 files changed, 52 insertions(+), 25 deletions(-)
diff --git a/src/Files.App/UserControls/StatusCenter/SpeedGraph.xaml b/src/Files.App/UserControls/StatusCenter/SpeedGraph.xaml
index cd9130943340..dcf39a9b50d0 100644
--- a/src/Files.App/UserControls/StatusCenter/SpeedGraph.xaml
+++ b/src/Files.App/UserControls/StatusCenter/SpeedGraph.xaml
@@ -9,7 +9,4 @@
xmlns:numerics="using:System.Numerics"
Loaded="UserControl_Loaded"
Unloaded="UserControl_Unloaded"
- mc:Ignorable="d">
-
-
-
+ mc:Ignorable="d" />
diff --git a/src/Files.App/UserControls/StatusCenter/SpeedGraph.xaml.cs b/src/Files.App/UserControls/StatusCenter/SpeedGraph.xaml.cs
index dd435af96fc4..10a85aea8199 100644
--- a/src/Files.App/UserControls/StatusCenter/SpeedGraph.xaml.cs
+++ b/src/Files.App/UserControls/StatusCenter/SpeedGraph.xaml.cs
@@ -4,6 +4,7 @@
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Hosting;
+using Microsoft.UI.Xaml.Media;
using System.Collections.Specialized;
using System.Numerics;
using Windows.UI;
@@ -24,7 +25,7 @@ public ObservableCollection Points
SetValue(PointsProperty, value);
}
}
-
+
public static readonly DependencyProperty PointsProperty =
DependencyProperty.Register(nameof(Points), typeof(ObservableCollection), typeof(SpeedGraph), null);
@@ -32,6 +33,7 @@ public ObservableCollection Points
ContainerVisual rootVisual;
ShapeVisual graphVisual;
CompositionSpriteShape graphShape;
+ SpriteVisual line;
InsetClip graphClip;
float width;
@@ -48,33 +50,52 @@ private void UserControl_Loaded(object sender, RoutedEventArgs e)
{
// is it a bad idea to recreate these on every load?
// TODO: it doesn't work the first time you open the flyout
- rootVisual = (ContainerVisual)ElementCompositionPreview.GetElementVisual(graphRoot);
- compositor = rootVisual.Compositor;
+ var temp = ElementCompositionPreview.GetElementVisual(this);
+ compositor = temp.Compositor;
+ rootVisual = compositor.CreateContainerVisual();
+ rootVisual.Size = temp.Size;
+ ElementCompositionPreview.SetElementChildVisual(this, rootVisual);
width = rootVisual.Size.X;
height = rootVisual.Size.Y;
+ var accentColor = (App.Current.Resources["AccentFillColorDefaultBrush"] as SolidColorBrush)!.Color;
+
var bgVisual = compositor.CreateSpriteVisual();
bgVisual.Size = rootVisual.Size;
- bgVisual.Brush = compositor.CreateColorBrush(Color.FromArgb(0x20, 0x40, 0xE0, 0xD0));
- rootVisual.Children.InsertAtBottom(bgVisual);
+ bgVisual.Brush = compositor.CreateColorBrush(Color.FromArgb(0x15, accentColor.R, accentColor.G, accentColor.B));
graphVisual = compositor.CreateShapeVisual();
graphVisual.Size = rootVisual.Size;
- rootVisual.Children.InsertAtBottom(graphVisual);
graphShape = compositor.CreateSpriteShape();
- // TODO: use accent theme resources
- graphShape.FillBrush = compositor.CreateColorBrush(Colors.Transparent);
- graphShape.StrokeBrush = compositor.CreateColorBrush(Colors.Turquoise);
+ var gradientFill = compositor.CreateLinearGradientBrush();
+ gradientFill.StartPoint = new(0.5f, 0f);
+ gradientFill.EndPoint = new(0.5f, 1f);
+ gradientFill.ColorStops.Add(compositor.CreateColorGradientStop(0f, Color.FromArgb(0x70, accentColor.R, accentColor.G, accentColor.B)));
+ gradientFill.ColorStops.Add(compositor.CreateColorGradientStop(1f, Color.FromArgb(0x06, accentColor.R, accentColor.G, accentColor.B)));
+ graphShape.FillBrush = gradientFill;
+ graphShape.StrokeBrush = compositor.CreateColorBrush(accentColor);
+ graphShape.StrokeThickness = 1f;
graphVisual.Shapes.Add(graphShape);
+ var container = compositor.CreateContainerVisual();
+ container.Size = rootVisual.Size;
+ container.Children.InsertAtBottom(bgVisual);
+ container.Children.InsertAtBottom(graphVisual);
+ rootVisual.Children.InsertAtBottom(container);
+
graphClip = compositor.CreateInsetClip();
graphClip.RightInset = width;
- rootVisual.Clip = graphClip;
+ container.Clip = graphClip;
- //// if it gets unloaded and reloaded because of the flyout closing
- //if (Points.Count > 1)
+ line = compositor.CreateSpriteVisual();
+ line.Size = new Vector2(width, 1.5f);
+ line.Brush = compositor.CreateColorBrush(accentColor);
+ rootVisual.Children.InsertAtTop(line);
+
+ // if it gets unloaded and reloaded because of the flyout closing
+ if (Points.Count > 0)
UpdateGraph();
Points.CollectionChanged += PointsChanged;
@@ -91,12 +112,6 @@ private void UserControl_Unloaded(object sender, RoutedEventArgs e)
private void PointsChanged(object? sender, NotifyCollectionChangedEventArgs e)
{
- if (e.Action != NotifyCollectionChangedAction.Add)
- return;
-
- if (Points[^1].Y > highestValue)
- highestValue = Points[^1].Y;
-
UpdateGraph();
}
@@ -104,7 +119,18 @@ void UpdateGraph()
{
var geometry = CreatePathFromPoints();
graphShape.Geometry = geometry;
- graphClip.RightInset = width - (width * Points[^1].X / 100f) + 1;
+
+ var lineAnim = compositor.CreateScalarKeyFrameAnimation();
+ lineAnim.InsertExpressionKeyFrame(0f, "this.StartingValue");
+ lineAnim.InsertKeyFrame(1f, height - (Points[^1].Y / highestValue) * (height - 40f) - 4, compositor.CreateLinearEasingFunction());
+ lineAnim.Duration = TimeSpan.FromMilliseconds(72);
+ line.StartAnimation("Offset.Y", lineAnim);
+
+ var clipAnim = compositor.CreateScalarKeyFrameAnimation();
+ clipAnim.InsertExpressionKeyFrame(0f, "this.StartingValue");
+ clipAnim.InsertKeyFrame(1f, width - (width * Points[^1].X / 100f) - 2, compositor.CreateLinearEasingFunction());
+ clipAnim.Duration = TimeSpan.FromMilliseconds(72);
+ graphClip.StartAnimation("RightInset", clipAnim);
}
CompositionPathGeometry CreatePathFromPoints()
@@ -113,10 +139,14 @@ CompositionPathGeometry CreatePathFromPoints()
pathBuilder.BeginFigure(0f, height);
for (int i = 0; i < Points.Count; i++)
{
+ if (Points[i].Y > highestValue)
+ highestValue = Points[i].Y;
// no smooth curve for now. a little ugly but maybe for the best performance-wise, we'll see before this gets merged
- pathBuilder.AddLine(width * Points[i].X / 100f, height - (Points[i].Y / highestValue) * (height * 0.9f));
+ pathBuilder.AddLine(width * Points[i].X / 100f, height - (Points[i].Y / highestValue) * (height - 40f) - 4);
}
- pathBuilder.AddLine(width * Points[^1].X / 100f, height);
+ // little extra part so that steep lines don't get cut off
+ pathBuilder.AddLine(width * Points[^1].X / 100f + 3, height - (Points[^1].Y / highestValue) * (height - 40f) - 4);
+ pathBuilder.AddLine(width * Points[^1].X / 100f + 3, height);
pathBuilder.EndFigure(CanvasFigureLoop.Closed);
var geometry = compositor.CreatePathGeometry();
geometry.Path = new CompositionPath(CanvasGeometry.CreatePath(pathBuilder));
From bd3bd7e893124b50cb4a932fa88bca76610437ae Mon Sep 17 00:00:00 2001
From: heftymouse <59918974+heftymouse@users.noreply.github.com>
Date: Fri, 7 Jun 2024 00:16:39 +0530
Subject: [PATCH 03/11] remove references and fix first time
---
.../UserControls/StatusCenter/SpeedGraph.xaml | 4 +-
.../StatusCenter/SpeedGraph.xaml.cs | 118 +++++++++++-------
2 files changed, 73 insertions(+), 49 deletions(-)
diff --git a/src/Files.App/UserControls/StatusCenter/SpeedGraph.xaml b/src/Files.App/UserControls/StatusCenter/SpeedGraph.xaml
index dcf39a9b50d0..a970c73ce987 100644
--- a/src/Files.App/UserControls/StatusCenter/SpeedGraph.xaml
+++ b/src/Files.App/UserControls/StatusCenter/SpeedGraph.xaml
@@ -6,7 +6,7 @@
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="using:Files.App.UserControls.StatusCenter"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
- xmlns:numerics="using:System.Numerics"
- Loaded="UserControl_Loaded"
+ ActualThemeChanged="UserControl_ActualThemeChanged"
+ SizeChanged="UserControl_SizeChanged"
Unloaded="UserControl_Unloaded"
mc:Ignorable="d" />
diff --git a/src/Files.App/UserControls/StatusCenter/SpeedGraph.xaml.cs b/src/Files.App/UserControls/StatusCenter/SpeedGraph.xaml.cs
index 10a85aea8199..e97bbeabd8b0 100644
--- a/src/Files.App/UserControls/StatusCenter/SpeedGraph.xaml.cs
+++ b/src/Files.App/UserControls/StatusCenter/SpeedGraph.xaml.cs
@@ -19,23 +19,23 @@ public sealed partial class SpeedGraph : UserControl
public ObservableCollection Points
{
get => (ObservableCollection)GetValue(PointsProperty);
- set
- {
- highestValue = 0;
- SetValue(PointsProperty, value);
- }
+ set => SetValue(PointsProperty, value);
}
public static readonly DependencyProperty PointsProperty =
DependencyProperty.Register(nameof(Points), typeof(ObservableCollection), typeof(SpeedGraph), null);
Compositor compositor;
+
ContainerVisual rootVisual;
- ShapeVisual graphVisual;
+
CompositionSpriteShape graphShape;
- SpriteVisual line;
InsetClip graphClip;
+ SpriteVisual line;
+
+ bool initialized;
+
float width;
float height;
@@ -46,14 +46,42 @@ public SpeedGraph()
this.InitializeComponent();
}
- private void UserControl_Loaded(object sender, RoutedEventArgs e)
+ private void UserControl_SizeChanged(object sender, SizeChangedEventArgs e)
+ {
+ if (initialized)
+ return;
+
+ Init();
+
+ Points.CollectionChanged += PointsChanged;
+ // added after first load
+ this.Loaded += OnLoaded;
+ }
+
+ private void OnLoaded(object sender, RoutedEventArgs e)
+ {
+ if (Points.Count > 0)
+ UpdateGraph();
+
+ Points.CollectionChanged += PointsChanged;
+ }
+
+ private void UserControl_Unloaded(object sender, RoutedEventArgs e)
+ {
+ Points.CollectionChanged -= PointsChanged;
+ }
+
+ private void PointsChanged(object? sender, NotifyCollectionChangedEventArgs e)
+ {
+ UpdateGraph();
+ }
+
+ private void Init()
{
- // is it a bad idea to recreate these on every load?
// TODO: it doesn't work the first time you open the flyout
- var temp = ElementCompositionPreview.GetElementVisual(this);
- compositor = temp.Compositor;
+ compositor = ElementCompositionPreview.GetElementVisual(this).Compositor;
rootVisual = compositor.CreateContainerVisual();
- rootVisual.Size = temp.Size;
+ rootVisual.Size = this.ActualSize;
ElementCompositionPreview.SetElementChildVisual(this, rootVisual);
width = rootVisual.Size.X;
@@ -61,21 +89,25 @@ private void UserControl_Loaded(object sender, RoutedEventArgs e)
var accentColor = (App.Current.Resources["AccentFillColorDefaultBrush"] as SolidColorBrush)!.Color;
+ var backgroundBrush = compositor.CreateColorBrush(accentColor with { A = 0x15 });
+
+ var graphFillBrush = compositor.CreateLinearGradientBrush();
+ graphFillBrush.StartPoint = new(0.5f, 0f);
+ graphFillBrush.EndPoint = new(0.5f, 1f);
+ graphFillBrush.ColorStops.Add(compositor.CreateColorGradientStop(0f, accentColor with { A = 0x70 }));
+ graphFillBrush.ColorStops.Add(compositor.CreateColorGradientStop(1f, accentColor with { A = 0x06 }));
+
+ var graphStrokeBrush = compositor.CreateColorBrush(accentColor);
+
var bgVisual = compositor.CreateSpriteVisual();
bgVisual.Size = rootVisual.Size;
- bgVisual.Brush = compositor.CreateColorBrush(Color.FromArgb(0x15, accentColor.R, accentColor.G, accentColor.B));
+ bgVisual.Brush = backgroundBrush;
- graphVisual = compositor.CreateShapeVisual();
+ var graphVisual = compositor.CreateShapeVisual();
graphVisual.Size = rootVisual.Size;
-
graphShape = compositor.CreateSpriteShape();
- var gradientFill = compositor.CreateLinearGradientBrush();
- gradientFill.StartPoint = new(0.5f, 0f);
- gradientFill.EndPoint = new(0.5f, 1f);
- gradientFill.ColorStops.Add(compositor.CreateColorGradientStop(0f, Color.FromArgb(0x70, accentColor.R, accentColor.G, accentColor.B)));
- gradientFill.ColorStops.Add(compositor.CreateColorGradientStop(1f, Color.FromArgb(0x06, accentColor.R, accentColor.G, accentColor.B)));
- graphShape.FillBrush = gradientFill;
- graphShape.StrokeBrush = compositor.CreateColorBrush(accentColor);
+ graphShape.FillBrush = graphFillBrush;
+ graphShape.StrokeBrush = graphStrokeBrush;
graphShape.StrokeThickness = 1f;
graphVisual.Shapes.Add(graphShape);
@@ -83,36 +115,21 @@ private void UserControl_Loaded(object sender, RoutedEventArgs e)
container.Size = rootVisual.Size;
container.Children.InsertAtBottom(bgVisual);
container.Children.InsertAtBottom(graphVisual);
- rootVisual.Children.InsertAtBottom(container);
graphClip = compositor.CreateInsetClip();
graphClip.RightInset = width;
container.Clip = graphClip;
+ rootVisual.Children.InsertAtBottom(container);
+
line = compositor.CreateSpriteVisual();
- line.Size = new Vector2(width, 1.5f);
- line.Brush = compositor.CreateColorBrush(accentColor);
+ line.Size = new(width, 1.5f);
+ line.Brush = graphStrokeBrush;
rootVisual.Children.InsertAtTop(line);
- // if it gets unloaded and reloaded because of the flyout closing
- if (Points.Count > 0)
- UpdateGraph();
-
- Points.CollectionChanged += PointsChanged;
- }
-
- private void UserControl_Unloaded(object sender, RoutedEventArgs e)
- {
- rootVisual.Children.RemoveAll();
- graphVisual = null!;
- graphShape = null!;
- graphClip = null!;
- Points.CollectionChanged -= PointsChanged;
- }
+ highestValue = 0;
- private void PointsChanged(object? sender, NotifyCollectionChangedEventArgs e)
- {
- UpdateGraph();
+ initialized = true;
}
void UpdateGraph()
@@ -128,14 +145,14 @@ void UpdateGraph()
var clipAnim = compositor.CreateScalarKeyFrameAnimation();
clipAnim.InsertExpressionKeyFrame(0f, "this.StartingValue");
- clipAnim.InsertKeyFrame(1f, width - (width * Points[^1].X / 100f) - 2, compositor.CreateLinearEasingFunction());
+ clipAnim.InsertKeyFrame(1f, width - (width * Points[^1].X / 100f) - 1, compositor.CreateLinearEasingFunction());
clipAnim.Duration = TimeSpan.FromMilliseconds(72);
graphClip.StartAnimation("RightInset", clipAnim);
}
CompositionPathGeometry CreatePathFromPoints()
{
- using var pathBuilder = new CanvasPathBuilder(null);
+ var pathBuilder = new CanvasPathBuilder(null);
pathBuilder.BeginFigure(0f, height);
for (int i = 0; i < Points.Count; i++)
{
@@ -145,12 +162,19 @@ CompositionPathGeometry CreatePathFromPoints()
pathBuilder.AddLine(width * Points[i].X / 100f, height - (Points[i].Y / highestValue) * (height - 40f) - 4);
}
// little extra part so that steep lines don't get cut off
- pathBuilder.AddLine(width * Points[^1].X / 100f + 3, height - (Points[^1].Y / highestValue) * (height - 40f) - 4);
- pathBuilder.AddLine(width * Points[^1].X / 100f + 3, height);
+ pathBuilder.AddLine(width * Points[^1].X / 100f + 2, height - (Points[^1].Y / highestValue) * (height - 40f) - 4);
+ pathBuilder.AddLine(width * Points[^1].X / 100f + 2, height);
pathBuilder.EndFigure(CanvasFigureLoop.Closed);
var geometry = compositor.CreatePathGeometry();
geometry.Path = new CompositionPath(CanvasGeometry.CreatePath(pathBuilder));
return geometry;
}
+
+ private void UserControl_ActualThemeChanged(FrameworkElement sender, object args)
+ {
+
+ }
+
+
}
}
From 5aae362acddc309e7fdc71eca2974b1610e7968e Mon Sep 17 00:00:00 2001
From: heftymouse <59918974+heftymouse@users.noreply.github.com>
Date: Fri, 7 Jun 2024 00:24:37 +0530
Subject: [PATCH 04/11] remove xaml
---
.../{SpeedGraph.xaml.cs => SpeedGraph.cs} | 9 ++++++---
.../UserControls/StatusCenter/SpeedGraph.xaml | 12 ------------
2 files changed, 6 insertions(+), 15 deletions(-)
rename src/Files.App/UserControls/StatusCenter/{SpeedGraph.xaml.cs => SpeedGraph.cs} (95%)
delete mode 100644 src/Files.App/UserControls/StatusCenter/SpeedGraph.xaml
diff --git a/src/Files.App/UserControls/StatusCenter/SpeedGraph.xaml.cs b/src/Files.App/UserControls/StatusCenter/SpeedGraph.cs
similarity index 95%
rename from src/Files.App/UserControls/StatusCenter/SpeedGraph.xaml.cs
rename to src/Files.App/UserControls/StatusCenter/SpeedGraph.cs
index e97bbeabd8b0..13bca7f5699b 100644
--- a/src/Files.App/UserControls/StatusCenter/SpeedGraph.xaml.cs
+++ b/src/Files.App/UserControls/StatusCenter/SpeedGraph.cs
@@ -14,7 +14,7 @@
namespace Files.App.UserControls.StatusCenter
{
- public sealed partial class SpeedGraph : UserControl
+ public sealed partial class SpeedGraph : Control
{
public ObservableCollection Points
{
@@ -43,10 +43,13 @@ public ObservableCollection Points
public SpeedGraph()
{
- this.InitializeComponent();
+ // TODO: unhook
+ this.SizeChanged += OnSizeChanged;
+ this.Unloaded += UserControl_Unloaded;
+ this.ActualThemeChanged += UserControl_ActualThemeChanged;
}
- private void UserControl_SizeChanged(object sender, SizeChangedEventArgs e)
+ private void OnSizeChanged(object sender, SizeChangedEventArgs e)
{
if (initialized)
return;
diff --git a/src/Files.App/UserControls/StatusCenter/SpeedGraph.xaml b/src/Files.App/UserControls/StatusCenter/SpeedGraph.xaml
deleted file mode 100644
index a970c73ce987..000000000000
--- a/src/Files.App/UserControls/StatusCenter/SpeedGraph.xaml
+++ /dev/null
@@ -1,12 +0,0 @@
-
-
From 8643be80e766e8440ad757360bf84f75e1541048 Mon Sep 17 00:00:00 2001
From: heftymouse <59918974+heftymouse@users.noreply.github.com>
Date: Fri, 7 Jun 2024 00:32:55 +0530
Subject: [PATCH 05/11] todone
---
.../UserControls/StatusCenter/SpeedGraph.cs | 20 +++++++++----------
1 file changed, 9 insertions(+), 11 deletions(-)
diff --git a/src/Files.App/UserControls/StatusCenter/SpeedGraph.cs b/src/Files.App/UserControls/StatusCenter/SpeedGraph.cs
index 13bca7f5699b..8ab1e4acd095 100644
--- a/src/Files.App/UserControls/StatusCenter/SpeedGraph.cs
+++ b/src/Files.App/UserControls/StatusCenter/SpeedGraph.cs
@@ -56,8 +56,8 @@ private void OnSizeChanged(object sender, SizeChangedEventArgs e)
Init();
+ // added *after* first load
Points.CollectionChanged += PointsChanged;
- // added after first load
this.Loaded += OnLoaded;
}
@@ -81,7 +81,6 @@ private void PointsChanged(object? sender, NotifyCollectionChangedEventArgs e)
private void Init()
{
- // TODO: it doesn't work the first time you open the flyout
compositor = ElementCompositionPreview.GetElementVisual(this).Compositor;
rootVisual = compositor.CreateContainerVisual();
rootVisual.Size = this.ActualSize;
@@ -135,18 +134,20 @@ private void Init()
initialized = true;
}
+ float YValue(float y) => height - (y / highestValue) * (height - 40f) - 4;
+
void UpdateGraph()
{
var geometry = CreatePathFromPoints();
graphShape.Geometry = geometry;
- var lineAnim = compositor.CreateScalarKeyFrameAnimation();
+ using var lineAnim = compositor.CreateScalarKeyFrameAnimation();
lineAnim.InsertExpressionKeyFrame(0f, "this.StartingValue");
- lineAnim.InsertKeyFrame(1f, height - (Points[^1].Y / highestValue) * (height - 40f) - 4, compositor.CreateLinearEasingFunction());
+ lineAnim.InsertKeyFrame(1f, YValue(Points[^1].Y), compositor.CreateLinearEasingFunction());
lineAnim.Duration = TimeSpan.FromMilliseconds(72);
line.StartAnimation("Offset.Y", lineAnim);
- var clipAnim = compositor.CreateScalarKeyFrameAnimation();
+ using var clipAnim = compositor.CreateScalarKeyFrameAnimation();
clipAnim.InsertExpressionKeyFrame(0f, "this.StartingValue");
clipAnim.InsertKeyFrame(1f, width - (width * Points[^1].X / 100f) - 1, compositor.CreateLinearEasingFunction());
clipAnim.Duration = TimeSpan.FromMilliseconds(72);
@@ -155,29 +156,26 @@ void UpdateGraph()
CompositionPathGeometry CreatePathFromPoints()
{
- var pathBuilder = new CanvasPathBuilder(null);
+ using var pathBuilder = new CanvasPathBuilder(null);
pathBuilder.BeginFigure(0f, height);
for (int i = 0; i < Points.Count; i++)
{
if (Points[i].Y > highestValue)
highestValue = Points[i].Y;
// no smooth curve for now. a little ugly but maybe for the best performance-wise, we'll see before this gets merged
- pathBuilder.AddLine(width * Points[i].X / 100f, height - (Points[i].Y / highestValue) * (height - 40f) - 4);
+ pathBuilder.AddLine(width * Points[i].X / 100f, YValue(Points[i].Y));
}
// little extra part so that steep lines don't get cut off
- pathBuilder.AddLine(width * Points[^1].X / 100f + 2, height - (Points[^1].Y / highestValue) * (height - 40f) - 4);
+ pathBuilder.AddLine(width * Points[^1].X / 100f + 2, YValue(Points[^1].Y));
pathBuilder.AddLine(width * Points[^1].X / 100f + 2, height);
pathBuilder.EndFigure(CanvasFigureLoop.Closed);
var geometry = compositor.CreatePathGeometry();
geometry.Path = new CompositionPath(CanvasGeometry.CreatePath(pathBuilder));
return geometry;
}
-
private void UserControl_ActualThemeChanged(FrameworkElement sender, object args)
{
}
-
-
}
}
From 8546538ce562eab419e53205b65a80d90335d97e Mon Sep 17 00:00:00 2001
From: heftymouse <59918974+heftymouse@users.noreply.github.com>
Date: Fri, 7 Jun 2024 18:01:53 +0530
Subject: [PATCH 06/11] oops regression
---
src/Files.App/UserControls/StatusCenter/SpeedGraph.cs | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/src/Files.App/UserControls/StatusCenter/SpeedGraph.cs b/src/Files.App/UserControls/StatusCenter/SpeedGraph.cs
index 8ab1e4acd095..8a2191e1d814 100644
--- a/src/Files.App/UserControls/StatusCenter/SpeedGraph.cs
+++ b/src/Files.App/UserControls/StatusCenter/SpeedGraph.cs
@@ -19,7 +19,11 @@ public sealed partial class SpeedGraph : Control
public ObservableCollection Points
{
get => (ObservableCollection)GetValue(PointsProperty);
- set => SetValue(PointsProperty, value);
+ set
+ {
+ highestValue = 0;
+ SetValue(PointsProperty, value);
+ }
}
public static readonly DependencyProperty PointsProperty =
From 5cff52712d085d7cada31cc9a27b0d3e00c61931 Mon Sep 17 00:00:00 2001
From: heftymouse <59918974+heftymouse@users.noreply.github.com>
Date: Wed, 12 Jun 2024 18:27:41 +0530
Subject: [PATCH 07/11] changes
---
.../UserControls/StatusCenter/SpeedGraph.cs | 42 +++++++++++--------
.../Utils/StatusCenter/StatusCenterItem.cs | 3 --
2 files changed, 24 insertions(+), 21 deletions(-)
diff --git a/src/Files.App/UserControls/StatusCenter/SpeedGraph.cs b/src/Files.App/UserControls/StatusCenter/SpeedGraph.cs
index 8a2191e1d814..d392b9b45320 100644
--- a/src/Files.App/UserControls/StatusCenter/SpeedGraph.cs
+++ b/src/Files.App/UserControls/StatusCenter/SpeedGraph.cs
@@ -33,11 +33,13 @@ public ObservableCollection Points
ContainerVisual rootVisual;
- CompositionSpriteShape graphShape;
+ CompositionPathGeometry graphGeometry;
InsetClip graphClip;
SpriteVisual line;
+ LinearEasingFunction linearEasing;
+
bool initialized;
float width;
@@ -90,8 +92,9 @@ private void Init()
rootVisual.Size = this.ActualSize;
ElementCompositionPreview.SetElementChildVisual(this, rootVisual);
- width = rootVisual.Size.X;
- height = rootVisual.Size.Y;
+ var size = rootVisual.Size;
+ width = size.X;
+ height = size.Y;
var accentColor = (App.Current.Resources["AccentFillColorDefaultBrush"] as SolidColorBrush)!.Color;
@@ -105,21 +108,23 @@ private void Init()
var graphStrokeBrush = compositor.CreateColorBrush(accentColor);
- var bgVisual = compositor.CreateSpriteVisual();
- bgVisual.Size = rootVisual.Size;
- bgVisual.Brush = backgroundBrush;
+ var container = compositor.CreateSpriteVisual();
+ container.Size = rootVisual.Size;
+ // container is also the graph background
+ container.Brush = backgroundBrush;
var graphVisual = compositor.CreateShapeVisual();
graphVisual.Size = rootVisual.Size;
- graphShape = compositor.CreateSpriteShape();
+ var graphShape = compositor.CreateSpriteShape();
graphShape.FillBrush = graphFillBrush;
graphShape.StrokeBrush = graphStrokeBrush;
graphShape.StrokeThickness = 1f;
+
+ graphGeometry = compositor.CreatePathGeometry();
+ graphShape.Geometry = graphGeometry;
+
graphVisual.Shapes.Add(graphShape);
- var container = compositor.CreateContainerVisual();
- container.Size = rootVisual.Size;
- container.Children.InsertAtBottom(bgVisual);
container.Children.InsertAtBottom(graphVisual);
graphClip = compositor.CreateInsetClip();
@@ -135,6 +140,8 @@ private void Init()
highestValue = 0;
+ linearEasing = compositor.CreateLinearEasingFunction();
+
initialized = true;
}
@@ -142,23 +149,23 @@ private void Init()
void UpdateGraph()
{
- var geometry = CreatePathFromPoints();
- graphShape.Geometry = geometry;
+ var path = CreatePathFromPoints();
+ graphGeometry.Path = path;
using var lineAnim = compositor.CreateScalarKeyFrameAnimation();
lineAnim.InsertExpressionKeyFrame(0f, "this.StartingValue");
- lineAnim.InsertKeyFrame(1f, YValue(Points[^1].Y), compositor.CreateLinearEasingFunction());
+ lineAnim.InsertKeyFrame(1f, YValue(Points[^1].Y), linearEasing);
lineAnim.Duration = TimeSpan.FromMilliseconds(72);
line.StartAnimation("Offset.Y", lineAnim);
using var clipAnim = compositor.CreateScalarKeyFrameAnimation();
clipAnim.InsertExpressionKeyFrame(0f, "this.StartingValue");
- clipAnim.InsertKeyFrame(1f, width - (width * Points[^1].X / 100f) - 1, compositor.CreateLinearEasingFunction());
+ clipAnim.InsertKeyFrame(1f, width - (width * Points[^1].X / 100f) - 1, linearEasing);
clipAnim.Duration = TimeSpan.FromMilliseconds(72);
graphClip.StartAnimation("RightInset", clipAnim);
}
- CompositionPathGeometry CreatePathFromPoints()
+ CompositionPath CreatePathFromPoints()
{
using var pathBuilder = new CanvasPathBuilder(null);
pathBuilder.BeginFigure(0f, height);
@@ -173,9 +180,8 @@ CompositionPathGeometry CreatePathFromPoints()
pathBuilder.AddLine(width * Points[^1].X / 100f + 2, YValue(Points[^1].Y));
pathBuilder.AddLine(width * Points[^1].X / 100f + 2, height);
pathBuilder.EndFigure(CanvasFigureLoop.Closed);
- var geometry = compositor.CreatePathGeometry();
- geometry.Path = new CompositionPath(CanvasGeometry.CreatePath(pathBuilder));
- return geometry;
+ var path = new CompositionPath(CanvasGeometry.CreatePath(pathBuilder));
+ return path;
}
private void UserControl_ActualThemeChanged(FrameworkElement sender, object args)
{
diff --git a/src/Files.App/Utils/StatusCenter/StatusCenterItem.cs b/src/Files.App/Utils/StatusCenter/StatusCenterItem.cs
index b60b68177c5e..7a259f10793d 100644
--- a/src/Files.App/Utils/StatusCenter/StatusCenterItem.cs
+++ b/src/Files.App/Utils/StatusCenter/StatusCenterItem.cs
@@ -372,9 +372,6 @@ private void ReportProgress(StatusCenterItemProgressModel value)
break;
}
- bool isSamePoint = false;
-
- // Add a new point
// 'debounce' updates a bit so the graph isn't too noisy
if (SpeedGraphValues.Count == 0 || (point.X - SpeedGraphValues[^1].X) > 0.5)
SpeedGraphValues?.Add(point);
From a0b374718863a8ffae31dd5e2404432e5b9b303d Mon Sep 17 00:00:00 2001
From: heftymouse <59918974+heftymouse@users.noreply.github.com>
Date: Sat, 15 Jun 2024 21:01:02 +0530
Subject: [PATCH 08/11] IT IS DONE.
---
.../UserControls/StatusCenter/SpeedGraph.cs | 93 +++++++++++++++----
1 file changed, 73 insertions(+), 20 deletions(-)
diff --git a/src/Files.App/UserControls/StatusCenter/SpeedGraph.cs b/src/Files.App/UserControls/StatusCenter/SpeedGraph.cs
index d392b9b45320..1b0104ced7e2 100644
--- a/src/Files.App/UserControls/StatusCenter/SpeedGraph.cs
+++ b/src/Files.App/UserControls/StatusCenter/SpeedGraph.cs
@@ -1,5 +1,4 @@
using Microsoft.Graphics.Canvas.Geometry;
-using Microsoft.UI;
using Microsoft.UI.Composition;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
@@ -7,7 +6,6 @@
using Microsoft.UI.Xaml.Media;
using System.Collections.Specialized;
using System.Numerics;
-using Windows.UI;
// To learn more about WinUI, the WinUI project structure,
// and more about our project templates, see: http://aka.ms/winui-project-info.
@@ -38,6 +36,11 @@ public ObservableCollection Points
SpriteVisual line;
+ CompositionColorBrush backgroundBrush;
+ CompositionColorGradientStop graphFillBottom;
+ CompositionColorGradientStop graphFillTop;
+ CompositionColorBrush graphStrokeBrush;
+
LinearEasingFunction linearEasing;
bool initialized;
@@ -46,13 +49,16 @@ public ObservableCollection Points
float height;
float highestValue;
+
+ IAppThemeModeService themeModeService;
public SpeedGraph()
- {
- // TODO: unhook
+ {
+ compositor = ElementCompositionPreview.GetElementVisual(this).Compositor;
+
+ themeModeService = Ioc.Default.GetRequiredService();
+
this.SizeChanged += OnSizeChanged;
- this.Unloaded += UserControl_Unloaded;
- this.ActualThemeChanged += UserControl_ActualThemeChanged;
}
private void OnSizeChanged(object sender, SizeChangedEventArgs e)
@@ -60,34 +66,59 @@ private void OnSizeChanged(object sender, SizeChangedEventArgs e)
if (initialized)
return;
- Init();
+ InitGraph();
+
+ this.SizeChanged -= OnSizeChanged;
// added *after* first load
- Points.CollectionChanged += PointsChanged;
this.Loaded += OnLoaded;
+ this.Unloaded += OnUnloaded;
+ Points.CollectionChanged += OnPointsChanged;
+ this.ActualThemeChanged += OnThemeChanged;
+ themeModeService.AppThemeModeChanged += OnAppThemeModeChanged;
}
private void OnLoaded(object sender, RoutedEventArgs e)
{
if (Points.Count > 0)
+ {
+ SetGraphColors();
UpdateGraph();
+ }
- Points.CollectionChanged += PointsChanged;
+ this.Unloaded += OnUnloaded;
+ Points.CollectionChanged += OnPointsChanged;
+ this.ActualThemeChanged += OnThemeChanged;
+ themeModeService.AppThemeModeChanged += OnAppThemeModeChanged;
}
- private void UserControl_Unloaded(object sender, RoutedEventArgs e)
+ private void OnUnloaded(object sender, RoutedEventArgs e)
{
- Points.CollectionChanged -= PointsChanged;
+ this.Unloaded -= OnUnloaded;
+ Points.CollectionChanged -= OnPointsChanged;
+ this.ActualThemeChanged -= OnThemeChanged;
+ themeModeService.AppThemeModeChanged -= OnAppThemeModeChanged;
}
- private void PointsChanged(object? sender, NotifyCollectionChangedEventArgs e)
+ private void OnPointsChanged(object? sender, NotifyCollectionChangedEventArgs e)
{
UpdateGraph();
}
- private void Init()
+ private void OnAppThemeModeChanged(object? sender, EventArgs e)
+ {
+ if (initialized)
+ SetGraphColors();
+ }
+
+ private void OnThemeChanged(FrameworkElement sender, object args)
+ {
+ if (initialized)
+ SetGraphColors();
+ }
+
+ private void InitGraph()
{
- compositor = ElementCompositionPreview.GetElementVisual(this).Compositor;
rootVisual = compositor.CreateContainerVisual();
rootVisual.Size = this.ActualSize;
ElementCompositionPreview.SetElementChildVisual(this, rootVisual);
@@ -96,17 +127,30 @@ private void Init()
width = size.X;
height = size.Y;
+ var rootClip = compositor.CreateRectangleClip();
+ rootClip.Top = 1.5f;
+ rootClip.Left = 1.5f;
+ rootClip.Bottom = height - 1.5f;
+ rootClip.Right = width - 2f; // i fear i might be a victim of DPI scaling here
+ rootClip.TopLeftRadius = new(4f);
+ rootClip.TopRightRadius = new(4f);
+ rootClip.BottomLeftRadius = new(4f);
+ rootClip.BottomRightRadius = new(4f);
+ rootVisual.Clip = rootClip;
+
var accentColor = (App.Current.Resources["AccentFillColorDefaultBrush"] as SolidColorBrush)!.Color;
- var backgroundBrush = compositor.CreateColorBrush(accentColor with { A = 0x15 });
+ backgroundBrush = compositor.CreateColorBrush(accentColor with { A = 0x0f });
var graphFillBrush = compositor.CreateLinearGradientBrush();
graphFillBrush.StartPoint = new(0.5f, 0f);
graphFillBrush.EndPoint = new(0.5f, 1f);
- graphFillBrush.ColorStops.Add(compositor.CreateColorGradientStop(0f, accentColor with { A = 0x70 }));
- graphFillBrush.ColorStops.Add(compositor.CreateColorGradientStop(1f, accentColor with { A = 0x06 }));
+ graphFillTop = compositor.CreateColorGradientStop(0f, accentColor with { A = 0x7f });
+ graphFillBottom = compositor.CreateColorGradientStop(1f, accentColor with { A = 0x0f });
+ graphFillBrush.ColorStops.Add(graphFillBottom);
+ graphFillBrush.ColorStops.Add(graphFillTop);
- var graphStrokeBrush = compositor.CreateColorBrush(accentColor);
+ graphStrokeBrush = compositor.CreateColorBrush(accentColor);
var container = compositor.CreateSpriteVisual();
container.Size = rootVisual.Size;
@@ -136,6 +180,7 @@ private void Init()
line = compositor.CreateSpriteVisual();
line.Size = new(width, 1.5f);
line.Brush = graphStrokeBrush;
+ line.Offset = new(0f, height - 4f, 0);
rootVisual.Children.InsertAtTop(line);
highestValue = 0;
@@ -145,7 +190,7 @@ private void Init()
initialized = true;
}
- float YValue(float y) => height - (y / highestValue) * (height - 40f) - 4;
+ float YValue(float y) => height - (y / highestValue) * (height - 48f) - 4;
void UpdateGraph()
{
@@ -183,9 +228,17 @@ CompositionPath CreatePathFromPoints()
var path = new CompositionPath(CanvasGeometry.CreatePath(pathBuilder));
return path;
}
- private void UserControl_ActualThemeChanged(FrameworkElement sender, object args)
+
+ void SetGraphColors()
{
+ var accentColor = (App.Current.Resources["AccentFillColorDefaultBrush"] as SolidColorBrush)!.Color;
+
+ backgroundBrush.Color = accentColor with { A = 0x0f };
+
+ graphFillTop.Color = accentColor with { A = 0x7f };
+ graphFillBottom.Color = accentColor with { A = 0x0f };
+ graphStrokeBrush.Color = accentColor;
}
}
}
From cba81e5df3d4457eab952d2b5048385b9b5fa598 Mon Sep 17 00:00:00 2001
From: heftymouse <59918974+heftymouse@users.noreply.github.com>
Date: Sun, 16 Jun 2024 15:38:38 +0530
Subject: [PATCH 09/11] fix accent color
---
.../Data/Contracts/IAppThemeModeService.cs | 6 +++++
.../Services/App/AppThemeModeService.cs | 16 ++++++++++-
.../UserControls/StatusCenter/SpeedGraph.cs | 27 ++++++++++---------
3 files changed, 35 insertions(+), 14 deletions(-)
diff --git a/src/Files.App/Data/Contracts/IAppThemeModeService.cs b/src/Files.App/Data/Contracts/IAppThemeModeService.cs
index 28311d8950b4..bb9dbfefbb13 100644
--- a/src/Files.App/Data/Contracts/IAppThemeModeService.cs
+++ b/src/Files.App/Data/Contracts/IAppThemeModeService.cs
@@ -3,6 +3,7 @@
using Microsoft.UI.Windowing;
using Microsoft.UI.Xaml;
+using Windows.UI;
namespace Files.App.Data.Contracts
{
@@ -18,6 +19,11 @@ public interface IAppThemeModeService
///
public ElementTheme AppThemeMode { get; set; }
+ ///
+ /// Gets the default accent fill color for the current theme mode.
+ ///
+ public Color DefaultAccentColor { get; }
+
///
/// Refreshes the application theme mode only for the main window.
///
diff --git a/src/Files.App/Services/App/AppThemeModeService.cs b/src/Files.App/Services/App/AppThemeModeService.cs
index b9e9c4c51358..c15085881d8d 100644
--- a/src/Files.App/Services/App/AppThemeModeService.cs
+++ b/src/Files.App/Services/App/AppThemeModeService.cs
@@ -5,6 +5,7 @@
using Microsoft.UI;
using Microsoft.UI.Windowing;
using Microsoft.UI.Xaml;
+using Microsoft.UI.Xaml.Media;
using Windows.Storage;
using Windows.UI;
using Windows.UI.ViewManagement;
@@ -34,6 +35,19 @@ public ElementTheme AppThemeMode
}
}
+ ///
+ public Color DefaultAccentColor
+ {
+ get => AppThemeMode switch
+ {
+ // these values are from the definition of AccentFillColorDefaultBrush in generic.xaml
+ // will have to be updated if WinUI changes in the future
+ ElementTheme.Light => (Color)(App.Current.Resources["SystemAccentColorDark1"]),
+ ElementTheme.Dark => (Color)(App.Current.Resources["SystemAccentColorLight2"]),
+ ElementTheme.Default or _ => (App.Current.Resources["AccentFillColorDefaultBrush"] as SolidColorBrush)!.Color
+ };
+ }
+
///
public event EventHandler? AppThemeModeChanged;
@@ -99,7 +113,7 @@ public void SetAppThemeMode(Window? window = null, AppWindowTitleBar? titleBar =
}
catch (Exception ex)
{
- App.Logger.LogWarning(ex, "Failed to change theme mode of the app.");
+ App.Logger.LogWarning(ex, "Failed to change theme mode of the app.");
}
}
diff --git a/src/Files.App/UserControls/StatusCenter/SpeedGraph.cs b/src/Files.App/UserControls/StatusCenter/SpeedGraph.cs
index 1b0104ced7e2..e55dc9be9395 100644
--- a/src/Files.App/UserControls/StatusCenter/SpeedGraph.cs
+++ b/src/Files.App/UserControls/StatusCenter/SpeedGraph.cs
@@ -3,7 +3,6 @@
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Hosting;
-using Microsoft.UI.Xaml.Media;
using System.Collections.Specialized;
using System.Numerics;
@@ -107,6 +106,7 @@ private void OnPointsChanged(object? sender, NotifyCollectionChangedEventArgs e)
private void OnAppThemeModeChanged(object? sender, EventArgs e)
{
+ // this seemingly doesn't fire? leaving it here in case it does in the future (if it's ever used outside of the flyout)
if (initialized)
SetGraphColors();
}
@@ -131,26 +131,28 @@ private void InitGraph()
rootClip.Top = 1.5f;
rootClip.Left = 1.5f;
rootClip.Bottom = height - 1.5f;
- rootClip.Right = width - 2f; // i fear i might be a victim of DPI scaling here
+ rootClip.Right = width - 2f;
rootClip.TopLeftRadius = new(4f);
rootClip.TopRightRadius = new(4f);
rootClip.BottomLeftRadius = new(4f);
rootClip.BottomRightRadius = new(4f);
rootVisual.Clip = rootClip;
- var accentColor = (App.Current.Resources["AccentFillColorDefaultBrush"] as SolidColorBrush)!.Color;
-
- backgroundBrush = compositor.CreateColorBrush(accentColor with { A = 0x0f });
+ backgroundBrush = compositor.CreateColorBrush();
var graphFillBrush = compositor.CreateLinearGradientBrush();
graphFillBrush.StartPoint = new(0.5f, 0f);
graphFillBrush.EndPoint = new(0.5f, 1f);
- graphFillTop = compositor.CreateColorGradientStop(0f, accentColor with { A = 0x7f });
- graphFillBottom = compositor.CreateColorGradientStop(1f, accentColor with { A = 0x0f });
+ graphFillTop = compositor.CreateColorGradientStop();
+ graphFillTop.Offset = 0f;
+ graphFillBottom = compositor.CreateColorGradientStop();
+ graphFillBottom.Offset = 1f;
graphFillBrush.ColorStops.Add(graphFillBottom);
graphFillBrush.ColorStops.Add(graphFillTop);
- graphStrokeBrush = compositor.CreateColorBrush(accentColor);
+ graphStrokeBrush = compositor.CreateColorBrush();
+
+ SetGraphColors();
var container = compositor.CreateSpriteVisual();
container.Size = rootVisual.Size;
@@ -198,13 +200,11 @@ void UpdateGraph()
graphGeometry.Path = path;
using var lineAnim = compositor.CreateScalarKeyFrameAnimation();
- lineAnim.InsertExpressionKeyFrame(0f, "this.StartingValue");
lineAnim.InsertKeyFrame(1f, YValue(Points[^1].Y), linearEasing);
lineAnim.Duration = TimeSpan.FromMilliseconds(72);
line.StartAnimation("Offset.Y", lineAnim);
using var clipAnim = compositor.CreateScalarKeyFrameAnimation();
- clipAnim.InsertExpressionKeyFrame(0f, "this.StartingValue");
clipAnim.InsertKeyFrame(1f, width - (width * Points[^1].X / 100f) - 1, linearEasing);
clipAnim.Duration = TimeSpan.FromMilliseconds(72);
graphClip.StartAnimation("RightInset", clipAnim);
@@ -231,12 +231,13 @@ CompositionPath CreatePathFromPoints()
void SetGraphColors()
{
- var accentColor = (App.Current.Resources["AccentFillColorDefaultBrush"] as SolidColorBrush)!.Color;
+ var accentColor = themeModeService.DefaultAccentColor;
- backgroundBrush.Color = accentColor with { A = 0x0f };
+ var veryLightColor = accentColor with { A = 0x0f };
+ backgroundBrush.Color = veryLightColor;
graphFillTop.Color = accentColor with { A = 0x7f };
- graphFillBottom.Color = accentColor with { A = 0x0f };
+ graphFillBottom.Color = veryLightColor;
graphStrokeBrush.Color = accentColor;
}
From 51499a7d82ed39cfd6b7e4a699b46f67fc605fa2 Mon Sep 17 00:00:00 2001
From: heftymouse <59918974+heftymouse@users.noreply.github.com>
Date: Sun, 16 Jun 2024 16:07:43 +0530
Subject: [PATCH 10/11] actually fix the colors this time
---
src/Files.App/UserControls/StatusCenter/SpeedGraph.cs | 11 ++++++++++-
1 file changed, 10 insertions(+), 1 deletion(-)
diff --git a/src/Files.App/UserControls/StatusCenter/SpeedGraph.cs b/src/Files.App/UserControls/StatusCenter/SpeedGraph.cs
index e55dc9be9395..5aa80607dd6d 100644
--- a/src/Files.App/UserControls/StatusCenter/SpeedGraph.cs
+++ b/src/Files.App/UserControls/StatusCenter/SpeedGraph.cs
@@ -3,8 +3,10 @@
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Hosting;
+using Microsoft.UI.Xaml.Media;
using System.Collections.Specialized;
using System.Numerics;
+using Windows.UI;
// To learn more about WinUI, the WinUI project structure,
// and more about our project templates, see: http://aka.ms/winui-project-info.
@@ -234,9 +236,16 @@ void SetGraphColors()
var accentColor = themeModeService.DefaultAccentColor;
var veryLightColor = accentColor with { A = 0x0f };
+
+ var slightlyDarkerColor = this.ActualTheme switch
+ {
+ ElementTheme.Light => accentColor with { A = 0x55 },
+ _ => accentColor with { A = 0x7f }
+ };
+
backgroundBrush.Color = veryLightColor;
- graphFillTop.Color = accentColor with { A = 0x7f };
+ graphFillTop.Color = slightlyDarkerColor;
graphFillBottom.Color = veryLightColor;
graphStrokeBrush.Color = accentColor;
From 6ce21bceb5c0bbec9a0cf7c6215f18d2d48987a7 Mon Sep 17 00:00:00 2001
From: Yair <39923744+yaira2@users.noreply.github.com>
Date: Mon, 17 Jun 2024 17:45:49 -0400
Subject: [PATCH 11/11] Update StatusCenter.xaml
---
src/Files.App/UserControls/StatusCenter/StatusCenter.xaml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/Files.App/UserControls/StatusCenter/StatusCenter.xaml b/src/Files.App/UserControls/StatusCenter/StatusCenter.xaml
index b9f194ff05db..22f968754810 100644
--- a/src/Files.App/UserControls/StatusCenter/StatusCenter.xaml
+++ b/src/Files.App/UserControls/StatusCenter/StatusCenter.xaml
@@ -227,7 +227,7 @@