-
-
Notifications
You must be signed in to change notification settings - Fork 2.6k
Add taskbar progress indicator support (#2695) #20621
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
7796d54
42c279e
0ede26a
c616dd3
6aa2637
252c578
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,4 +1,24 @@ | ||
| <Window xmlns="https://github.com/avaloniaui" | ||
| xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml' | ||
| x:Class="Sandbox.MainWindow"> | ||
| x:Class="Sandbox.MainWindow" | ||
| Title="Taskbar Progress Demo" | ||
| Width="400" Height="350"> | ||
| <StackPanel Margin="20" Spacing="12"> | ||
| <TextBlock Text="Taskbar Progress Demo" FontSize="20" FontWeight="Bold"/> | ||
|
|
||
| <TextBlock Text="State:" Margin="0,10,0,0"/> | ||
| <ComboBox x:Name="StateCombo" SelectedIndex="0"> | ||
| <ComboBoxItem Content="None"/> | ||
| <ComboBoxItem Content="Indeterminate"/> | ||
| <ComboBoxItem Content="Normal"/> | ||
| <ComboBoxItem Content="Error"/> | ||
| <ComboBoxItem Content="Paused"/> | ||
| </ComboBox> | ||
|
|
||
| <TextBlock x:Name="ValueLabel" Text="Value: 0%" Margin="0,10,0,0"/> | ||
| <Slider x:Name="ProgressSlider" Minimum="0" Maximum="100" Value="0"/> | ||
|
|
||
| <Button x:Name="AnimateBtn" Content="Animate 0 -> 100%" Margin="0,10,0,0"/> | ||
| <Button x:Name="ResetBtn" Content="Reset"/> | ||
| </StackPanel> | ||
| </Window> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,17 +1,71 @@ | ||
| using Avalonia; | ||
| using System; | ||
| using Avalonia.Controls; | ||
| using Avalonia.Controls.Presenters; | ||
| using Avalonia.Input.TextInput; | ||
| using Avalonia.Markup.Xaml; | ||
| using Avalonia.Win32.WinRT.Composition; | ||
| using Avalonia.Threading; | ||
|
|
||
| namespace Sandbox | ||
| { | ||
| public partial class MainWindow : Window | ||
| { | ||
| private DispatcherTimer? _timer; | ||
|
|
||
| public MainWindow() | ||
| { | ||
| InitializeComponent(); | ||
|
|
||
| var stateCombo = this.FindControl<ComboBox>("StateCombo")!; | ||
| var slider = this.FindControl<Slider>("ProgressSlider")!; | ||
| var valueLabel = this.FindControl<TextBlock>("ValueLabel")!; | ||
| var animateBtn = this.FindControl<Button>("AnimateBtn")!; | ||
| var resetBtn = this.FindControl<Button>("ResetBtn")!; | ||
|
|
||
| stateCombo.SelectionChanged += (_, _) => | ||
| { | ||
| TaskbarProgressState = stateCombo.SelectedIndex switch | ||
| { | ||
| 0 => Avalonia.Controls.TaskbarProgressState.None, | ||
| 1 => Avalonia.Controls.TaskbarProgressState.Indeterminate, | ||
| 2 => Avalonia.Controls.TaskbarProgressState.Normal, | ||
| 3 => Avalonia.Controls.TaskbarProgressState.Error, | ||
| 4 => Avalonia.Controls.TaskbarProgressState.Paused, | ||
| _ => Avalonia.Controls.TaskbarProgressState.None, | ||
| }; | ||
| }; | ||
|
|
||
| slider.PropertyChanged += (_, e) => | ||
| { | ||
| if (e.Property == Slider.ValueProperty) | ||
| { | ||
| var pct = slider.Value / 100.0; | ||
| TaskbarProgressValue = pct; | ||
| valueLabel.Text = $"Value: {slider.Value:F0}%"; | ||
| } | ||
| }; | ||
|
|
||
| animateBtn.Click += (_, _) => | ||
| { | ||
| _timer?.Stop(); | ||
| slider.Value = 0; | ||
| TaskbarProgressState = Avalonia.Controls.TaskbarProgressState.Normal; | ||
| stateCombo.SelectedIndex = 2; | ||
|
|
||
| _timer = new DispatcherTimer { Interval = TimeSpan.FromMilliseconds(50) }; | ||
| _timer.Tick += (_, _) => | ||
| { | ||
| slider.Value += 1; | ||
| if (slider.Value >= 100) | ||
| _timer.Stop(); | ||
| }; | ||
| _timer.Start(); | ||
| }; | ||
|
|
||
| resetBtn.Click += (_, _) => | ||
| { | ||
| _timer?.Stop(); | ||
| slider.Value = 0; | ||
| stateCombo.SelectedIndex = 0; | ||
| TaskbarProgressState = Avalonia.Controls.TaskbarProgressState.None; | ||
| TaskbarProgressValue = 0; | ||
| }; | ||
| } | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,33 @@ | ||
| namespace Avalonia.Controls | ||
| { | ||
| /// <summary> | ||
| /// Specifies the state of the progress indicator displayed in the taskbar. | ||
| /// </summary> | ||
| public enum TaskbarProgressState | ||
| { | ||
| /// <summary> | ||
| /// No progress is displayed. | ||
| /// </summary> | ||
| None = 0, | ||
|
|
||
| /// <summary> | ||
| /// Pulsing green indicator is displayed. | ||
| /// </summary> | ||
| Indeterminate = 1, | ||
|
|
||
| /// <summary> | ||
| /// Green progress indicator is displayed. | ||
| /// </summary> | ||
| Normal = 2, | ||
|
|
||
| /// <summary> | ||
| /// Red progress indicator is displayed. | ||
| /// </summary> | ||
| Error = 4, | ||
|
|
||
| /// <summary> | ||
| /// Yellow progress indicator is displayed. | ||
| /// </summary> | ||
| Paused = 8, | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -151,6 +151,18 @@ public class Window : WindowBase, IFocusScope, ILayoutRoot | |
| public static readonly StyledProperty<bool> ShowInTaskbarProperty = | ||
| AvaloniaProperty.Register<Window, bool>(nameof(ShowInTaskbar), true); | ||
|
|
||
| /// <summary> | ||
| /// Defines the <see cref="TaskbarProgressState"/> property. | ||
| /// </summary> | ||
| public static readonly StyledProperty<TaskbarProgressState> TaskbarProgressStateProperty = | ||
| AvaloniaProperty.Register<Window, TaskbarProgressState>(nameof(TaskbarProgressState), TaskbarProgressState.None); | ||
|
|
||
| /// <summary> | ||
| /// Defines the <see cref="TaskbarProgressValue"/> property. | ||
| /// </summary> | ||
| public static readonly StyledProperty<double> TaskbarProgressValueProperty = | ||
| AvaloniaProperty.Register<Window, double>(nameof(TaskbarProgressValue), 0.0); | ||
|
Comment on lines
+157
to
+164
|
||
|
|
||
| /// <summary> | ||
| /// Defines the <see cref="ClosingBehavior"/> property. | ||
| /// </summary> | ||
|
|
@@ -254,6 +266,8 @@ public Window(IWindowImpl impl) | |
| CreatePlatformImplBinding(CanMinimizeProperty, canMinimize => PlatformImpl!.SetCanMinimize(canMinimize)); | ||
| CreatePlatformImplBinding(CanMaximizeProperty, canMaximize => PlatformImpl!.SetCanMaximize(canMaximize)); | ||
| CreatePlatformImplBinding(ShowInTaskbarProperty, show => PlatformImpl!.ShowTaskbarIcon(show)); | ||
| CreatePlatformImplBinding(TaskbarProgressStateProperty, state => PlatformImpl!.SetTaskbarProgressState(state)); | ||
| CreatePlatformImplBinding(TaskbarProgressValueProperty, value => PlatformImpl!.SetTaskbarProgressValue((ulong)(Math.Clamp(value, 0.0, 1.0) * 1000), 1000)); | ||
|
|
||
| CreatePlatformImplBinding(WindowStateProperty, state => PlatformImpl!.WindowState = state); | ||
| CreatePlatformImplBinding(ExtendClientAreaToDecorationsHintProperty, hint => PlatformImpl!.SetExtendClientAreaToDecorationsHint(hint)); | ||
|
|
@@ -389,13 +403,31 @@ public bool ShowActivated | |
| /// <summary> | ||
| /// Enables or disables the taskbar icon | ||
| /// </summary> | ||
| /// | ||
| /// | ||
| public bool ShowInTaskbar | ||
| { | ||
| get => GetValue(ShowInTaskbarProperty); | ||
| set => SetValue(ShowInTaskbarProperty, value); | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Gets or sets the taskbar progress indicator state for this window. | ||
| /// </summary> | ||
| public TaskbarProgressState TaskbarProgressState | ||
| { | ||
| get => GetValue(TaskbarProgressStateProperty); | ||
| set => SetValue(TaskbarProgressStateProperty, value); | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Gets or sets the taskbar progress indicator value (0.0 to 1.0) for this window. | ||
| /// </summary> | ||
| public double TaskbarProgressValue | ||
| { | ||
| get => GetValue(TaskbarProgressValueProperty); | ||
| set => SetValue(TaskbarProgressValueProperty, value); | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Gets or sets a value indicating how the <see cref="Closing"/> event behaves in the presence | ||
| /// of child windows. | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The TaskbarProgressValue property doesn't validate that the input is within the expected range of 0.0 to 1.0. While the documentation states this range, accepting values outside this range could lead to unexpected behavior in platform implementations. Consider adding validation to clamp or throw an exception for out-of-range values, or document that values outside this range have undefined behavior.