- Notifications
You must be signed in to change notification settings - Fork 1.4k
Added radial progress bar control #828
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
Merged
Merged
Changes from 20 commits
Commits
Show all changes
22 commits Select commit Hold shift + click to select a range
fcb4271 Added radial progress bar
AnthroHeader d6037a0 Setting dependency properties to literal values crashes app
AnthroHeader 54eeeac Added sample to app
AnthroHeader d6bcb3a Fix
AnthroHeader ef1384b Fix
AnthroHeader 51b63de Rendering fix
AnthroHeader c0a37b8 Added documentation, better image
AnthroHeader 42713ef Documentation
AnthroHeader 0f5e5c3 Documentation
AnthroHeader 5ea19d2 Typo
AnthroHeader d48ddfa PR comment fixes
AnthroHeader c1fdbe8 Added additional dependency property for outline color, background se…
AnthroHeader 49bbae2 Documentation update
AnthroHeader e8fac72 Default thickness declared in template
AnthroHeader 480b60b Synced with upstream
AnthroHeader 680423c Updated with upstream
AnthroHeader 180a6af Fixed documentation formatting
AnthroHeader d99d028 Merge remote-tracking branch 'upstream/dev' into dev
0f6312d Deriving from Progressbar instead of RangeBase
93dcfb8 Fix
a9c2d9f Merge remote-tracking branch 'upstream/dev' into dev
94af716 Added outline color picker to sample page
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Binary file added BIN +5.94 KB ...osoft.Toolkit.Uwp.SampleApp/SamplePages/RadialProgressBar/RadialProgressBar.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
28 changes: 28 additions & 0 deletions 28 Microsoft.Toolkit.Uwp.SampleApp/SamplePages/RadialProgressBar/RadialProgressBarCode.bind
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,28 @@ | ||
| <Page x:Class="Microsoft.Toolkit.Uwp.SampleApp.SamplePages.RadialProgressBarPage" | ||
| xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" | ||
| xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" | ||
| xmlns:controls="using:Microsoft.Toolkit.Uwp.UI.Controls" | ||
| xmlns:d="http://schemas.microsoft.com/expression/blend/2008" | ||
| xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" | ||
| mc:Ignorable="d"> | ||
| | ||
| <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"> | ||
| <Grid VerticalAlignment="Center" | ||
| HorizontalAlignment="Center"> | ||
| <Grid.ColumnDefinitions> | ||
| <ColumnDefinition Width="50"></ColumnDefinition> | ||
| <ColumnDefinition Width="250"></ColumnDefinition> | ||
| <ColumnDefinition Width="50"></ColumnDefinition> | ||
| </Grid.ColumnDefinitions> | ||
| <controls:RadialProgressBar | ||
| x:Name="RadialProgressBar" | ||
| Grid.Column="1" | ||
| Value="@[Value:Slider:0:0-100]" | ||
| Thickness="@[Thickness:Slider:4:4-20]" | ||
| Minimum="0" | ||
| Maximum="100" | ||
| Width="@[Width:Slider:100:100-200]" | ||
| Height="@[Height:Slider:100:100-200]"/> | ||
| </Grid> | ||
| </Grid> | ||
| </Page> | ||
27 changes: 27 additions & 0 deletions 27 Microsoft.Toolkit.Uwp.SampleApp/SamplePages/RadialProgressBar/RadialProgressBarPage.xaml
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| <Page x:Class="Microsoft.Toolkit.Uwp.SampleApp.SamplePages.RadialProgressBarPage" | ||
| xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" | ||
| xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" | ||
| xmlns:controls="using:Microsoft.Toolkit.Uwp.UI.Controls" | ||
| xmlns:d="http://schemas.microsoft.com/expression/blend/2008" | ||
| xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" | ||
| mc:Ignorable="d"> | ||
| | ||
| <Grid Background="{StaticResource Brush-Grey-05}"> | ||
| <Grid HorizontalAlignment="Center" | ||
| VerticalAlignment="Center"> | ||
| <Grid.ColumnDefinitions> | ||
| <ColumnDefinition Width="50" /> | ||
| <ColumnDefinition Width="250" /> | ||
| <ColumnDefinition Width="50" /> | ||
| </Grid.ColumnDefinitions> | ||
| <controls:RadialProgressBar x:Name="RadialProgressBarControl" | ||
| Grid.Column="1" | ||
| Maximum="100" | ||
| Minimum="0" | ||
| Thickness="{Binding Thickness.Value, Mode=OneWay}" | ||
| Value="{Binding Value.Value, Mode=OneWay}" | ||
| Width="{Binding Width.Value, Mode=OneWay}" | ||
| Height="{Binding Height.Value, Mode=OneWay}"/> | ||
| </Grid> | ||
| </Grid> | ||
| </Page> |
39 changes: 39 additions & 0 deletions 39 Microsoft.Toolkit.Uwp.SampleApp/SamplePages/RadialProgressBar/RadialProgressBarPage.xaml.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,39 @@ | ||
| // ****************************************************************** | ||
| // Copyright (c) Microsoft. All rights reserved. | ||
| // This code is licensed under the MIT License (MIT). | ||
| // THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, | ||
| // INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | ||
| // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, | ||
| // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | ||
| // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH | ||
| // THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE. | ||
| // ****************************************************************** | ||
| | ||
| using Microsoft.Toolkit.Uwp.SampleApp.Models; | ||
| | ||
| using Windows.UI.Xaml.Controls; | ||
| using Windows.UI.Xaml.Navigation; | ||
| | ||
| namespace Microsoft.Toolkit.Uwp.SampleApp.SamplePages | ||
| { | ||
| public sealed partial class RadialProgressBarPage : Page | ||
| { | ||
| public RadialProgressBarPage() | ||
| { | ||
| InitializeComponent(); | ||
| } | ||
| | ||
| protected override void OnNavigatedTo(NavigationEventArgs e) | ||
| { | ||
| base.OnNavigatedTo(e); | ||
| | ||
| var propertyDesc = e.Parameter as PropertyDescriptor; | ||
| | ||
| if (propertyDesc != null) | ||
| { | ||
| DataContext = propertyDesc.Expando; | ||
| } | ||
| } | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
204 changes: 204 additions & 0 deletions 204 Microsoft.Toolkit.Uwp.UI.Controls/RadialProgressBar/RadialProgressBar.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,204 @@ | ||
| // ****************************************************************** | ||
| // Copyright (c) Microsoft. All rights reserved. | ||
| // This code is licensed under the MIT License (MIT). | ||
| // THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, | ||
| // INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | ||
| // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, | ||
| // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | ||
| // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH | ||
| // THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE. | ||
| // ****************************************************************** | ||
| | ||
| using System; | ||
| using Windows.Foundation; | ||
| using Windows.UI.Xaml; | ||
| using Windows.UI.Xaml.Controls; | ||
| using Windows.UI.Xaml.Media; | ||
| | ||
| namespace Microsoft.Toolkit.Uwp.UI.Controls | ||
| { | ||
| /// <summary> | ||
| /// An alternative impementation of a progress bar. | ||
| /// Progression is represented by a loop filling up in a clockwise fashion. | ||
| /// Like the traditional progress bar, it inherits from RangeBase, so Minimum, Maximum and Value properties work the same way. | ||
| /// </summary> | ||
| [TemplatePart(Name = OutlineFigurePartName, Type = typeof(PathFigure))] | ||
| [TemplatePart(Name = OutlineArcPartName, Type = typeof(ArcSegment))] | ||
| [TemplatePart(Name = BarFigurePartName, Type = typeof(PathFigure))] | ||
| [TemplatePart(Name = BarArcPartName, Type = typeof(ArcSegment))] | ||
| public sealed class RadialProgressBar : ProgressBar | ||
| { | ||
| private const string OutlineFigurePartName = "OutlineFigurePart"; | ||
| private const string OutlineArcPartName = "OutlineArcPart"; | ||
| private const string BarFigurePartName = "BarFigurePart"; | ||
| private const string BarArcPartName = "BarArcPart"; | ||
| | ||
| private PathFigure outlineFigure; | ||
| private PathFigure barFigure; | ||
| private ArcSegment outlineArc; | ||
| private ArcSegment barArc; | ||
| | ||
| private bool allTemplatePartsDefined = false; | ||
| | ||
| /// <summary> | ||
| /// Called when the Minimum property changes. | ||
| /// </summary> | ||
| /// <param name="oldMinimum">Old value of the Minimum property.</param> | ||
| /// <param name="newMinimum">New value of the Minimum property.</param> | ||
| protected override void OnMinimumChanged(double oldMinimum, double newMinimum) | ||
| { | ||
| base.OnMinimumChanged(oldMinimum, newMinimum); | ||
| RenderSegment(); | ||
| } | ||
| | ||
| /// <summary> | ||
| /// Called when the Maximum property changes. | ||
| /// </summary> | ||
| /// <param name="oldMaximum">Old value of the Maximum property.</param> | ||
| /// <param name="newMaximum">New value of the Maximum property.</param> | ||
| protected override void OnMaximumChanged(double oldMaximum, double newMaximum) | ||
| { | ||
| base.OnMaximumChanged(oldMaximum, newMaximum); | ||
| RenderSegment(); | ||
| } | ||
| | ||
| /// <summary> | ||
| /// Called when the Value property changes. | ||
| /// </summary> | ||
| /// <param name="oldValue">Old value of the Value property.</param> | ||
| /// <param name="newValue">New value of the Value property.</param> | ||
| protected override void OnValueChanged(double oldValue, double newValue) | ||
| { | ||
| base.OnValueChanged(oldValue, newValue); | ||
| RenderSegment(); | ||
| } | ||
| | ||
| /// <summary> | ||
| /// Update the visual state of the control when its template is changed. | ||
| /// </summary> | ||
| protected override void OnApplyTemplate() | ||
| { | ||
| base.OnApplyTemplate(); | ||
| | ||
| outlineFigure = GetTemplateChild(OutlineFigurePartName) as PathFigure; | ||
| outlineArc = GetTemplateChild(OutlineArcPartName) as ArcSegment; | ||
| barFigure = GetTemplateChild(BarFigurePartName) as PathFigure; | ||
| barArc = GetTemplateChild(BarArcPartName) as ArcSegment; | ||
| | ||
| allTemplatePartsDefined = outlineFigure != null && outlineArc != null && barFigure != null && barArc != null; | ||
| | ||
| RenderAll(); | ||
| } | ||
| | ||
| /// <summary> | ||
| /// Gets or sets the thickness of the circular ouline and segment | ||
| /// </summary> | ||
| public double Thickness | ||
| { | ||
| get { return (double)GetValue(ThicknessProperty); } | ||
| set { SetValue(ThicknessProperty, value); } | ||
| } | ||
| | ||
| /// <summary> | ||
| /// Identifies the Thickness dependency property | ||
| /// </summary> | ||
| public static readonly DependencyProperty ThicknessProperty = DependencyProperty.Register(nameof(Thickness), typeof(double), typeof(RadialProgressBar), new PropertyMetadata(0.0, ThicknessChangedHandler)); | ||
| | ||
| /// <summary> | ||
| /// Gets or sets the color of the circular ouline on which the segment is drawn | ||
| /// </summary> | ||
| public Brush Outline | ||
| { | ||
| get { return (Brush)GetValue(OutlineProperty); } | ||
| set { SetValue(OutlineProperty, value); } | ||
| } | ||
| | ||
| /// <summary> | ||
| /// Identifies the Outline dependency property | ||
| /// </summary> | ||
| public static readonly DependencyProperty OutlineProperty = DependencyProperty.Register(nameof(Outline), typeof(Brush), typeof(RadialProgressBar), new PropertyMetadata(new SolidColorBrush(Windows.UI.Colors.Transparent))); | ||
| Contributor There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Would it make sense to use the same property names as ProgressBar for the Background color? In other words, wondering if this property is needed? | ||
| | ||
| /// <summary> | ||
| /// Initializes a new instance of the <see cref="RadialProgressBar"/> class. | ||
| /// Create a default circular progress bar | ||
| /// </summary> | ||
| public RadialProgressBar() | ||
| { | ||
| DefaultStyleKey = typeof(RadialProgressBar); | ||
| SizeChanged += SizeChangedHandler; | ||
| } | ||
| | ||
| // Render outline and progress segment when thickness is changed | ||
| private static void ThicknessChangedHandler(DependencyObject d, DependencyPropertyChangedEventArgs e) | ||
| { | ||
| var sender = d as RadialProgressBar; | ||
| sender.RenderAll(); | ||
| } | ||
| | ||
| // Render outline and progress segment when control is resized. | ||
| private void SizeChangedHandler(object sender, SizeChangedEventArgs e) | ||
| { | ||
| var self = sender as RadialProgressBar; | ||
| self.RenderAll(); | ||
| } | ||
| | ||
| private double ComputeNormalizedRange() | ||
| { | ||
| var range = Maximum - Minimum; | ||
| var delta = Value - Minimum; | ||
| var output = range == 0.0 ? 0.0 : delta / range; | ||
| output = Math.Min(Math.Max(0.0, output), 0.9999); | ||
| return output; | ||
| } | ||
| | ||
| // Compute size of ellipse so that the outer edge touches the bounding rectangle | ||
| private Size ComputeEllipseSize() | ||
| { | ||
| var safeThickness = Math.Max(Thickness, 0.0); | ||
| var width = Math.Max((ActualWidth - safeThickness) / 2.0, 0.0); | ||
| var height = Math.Max((ActualHeight - safeThickness) / 2.0, 0.0); | ||
| return new Size(width, height); | ||
| } | ||
| | ||
| // Render the segment representing progress ratio. | ||
| private void RenderSegment() | ||
| { | ||
| if (!allTemplatePartsDefined) | ||
| { | ||
| return; | ||
| } | ||
| | ||
| var normalizedRange = ComputeNormalizedRange(); | ||
| | ||
| var angle = 2 * Math.PI * normalizedRange; | ||
| var size = ComputeEllipseSize(); | ||
| var translationFactor = Math.Max(Thickness / 2.0, 0.0); | ||
| | ||
| double x = (Math.Sin(angle) * size.Width) + size.Width + translationFactor; | ||
| double y = (((Math.Cos(angle) * size.Height) - size.Height) * -1) + translationFactor; | ||
| | ||
| barArc.IsLargeArc = angle >= Math.PI; | ||
| barArc.Point = new Point(x, y); | ||
| } | ||
| | ||
| // Render the progress segment and the loop outline. Needs to run when control is resized or retemplated | ||
| private void RenderAll() | ||
| { | ||
| if (!allTemplatePartsDefined) | ||
| { | ||
| return; | ||
| } | ||
| | ||
| var size = ComputeEllipseSize(); | ||
| var segmentWidth = size.Width; | ||
| var translationFactor = Math.Max(Thickness / 2.0, 0.0); | ||
| | ||
| outlineFigure.StartPoint = barFigure.StartPoint = new Point(segmentWidth + translationFactor, translationFactor); | ||
| outlineArc.Size = barArc.Size = new Size(segmentWidth, size.Height); | ||
| outlineArc.Point = new Point(segmentWidth + translationFactor - 0.05, translationFactor); | ||
| | ||
| RenderSegment(); | ||
| } | ||
| } | ||
| } | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit. This suggestion is invalid because no changes were made to the code. Suggestions cannot be applied while the pull request is closed. Suggestions cannot be applied while viewing a subset of changes. Only one suggestion per line can be applied in a batch. Add this suggestion to a batch that can be applied as a single commit. Applying suggestions on deleted lines is not supported. You must change the existing code in this line in order to create a valid suggestion. Outdated suggestions cannot be applied. This suggestion has been applied or marked resolved. Suggestions cannot be applied from pending reviews. Suggestions cannot be applied on multi-line comments. Suggestions cannot be applied while the pull request is queued to merge. Suggestion cannot be applied right now. Please check back later.
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.
Would it make sense to also add the Color enum for the Outline(Background) and Foreground so the show up as properties?