Skip to content

Commit

Permalink
Progress Controls Template Settings from WUXC + Re-Templating Tests (m…
Browse files Browse the repository at this point in the history
  • Loading branch information
Kinnara committed Apr 30, 2020
1 parent 71544a8 commit 7bd16ce
Show file tree
Hide file tree
Showing 19 changed files with 1,374 additions and 329 deletions.
121 changes: 83 additions & 38 deletions ModernWpf.Controls/ProgressRing/ProgressRing.cs
Expand Up @@ -7,19 +7,12 @@

namespace ModernWpf.Controls
{
[TemplateVisualState(GroupName = SizeStatesGroup, Name = LargeState)]
[TemplateVisualState(GroupName = SizeStatesGroup, Name = SmallState)]
[TemplateVisualState(GroupName = ActiveStatesGroup, Name = InactiveState)]
[TemplateVisualState(GroupName = ActiveStatesGroup, Name = ActiveState)]
public class ProgressRing : Control
{
private const string SizeStatesGroup = "SizeStates";
private const string LargeState = "Large";
private const string SmallState = "Small";

private const string ActiveStatesGroup = "ActiveStates";
private const string InactiveState = "Inactive";
private const string ActiveState = "Active";
const string s_ActiveStateName = "Active";
const string s_InactiveStateName = "Inactive";
const string s_SmallStateName = "Small";
const string s_LargeStateName = "Large";

static ProgressRing()
{
Expand All @@ -28,12 +21,9 @@ static ProgressRing()

public ProgressRing()
{
TemplateSettings = new ProgressRingTemplateSettings();
}
SetValue(TemplateSettingsPropertyKey, new ProgressRingTemplateSettings());

protected override AutomationPeer OnCreateAutomationPeer()
{
return new ProgressRingAutomationPeer(this);
SizeChanged += OnSizeChanged;
}

#region IsActive
Expand All @@ -49,47 +39,102 @@ public bool IsActive
nameof(IsActive),
typeof(bool),
typeof(ProgressRing),
new FrameworkPropertyMetadata(OnIsActiveChanged));
new FrameworkPropertyMetadata(OnIsActivePropertyChanged));

private static void OnIsActivePropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args)
{
((ProgressRing)sender).OnIsActivePropertyChanged(args);
}

#endregion

#region TemplateSettings

private static readonly DependencyPropertyKey TemplateSettingsPropertyKey =
DependencyProperty.RegisterReadOnly(
nameof(TemplateSettings),
typeof(ProgressRingTemplateSettings),
typeof(ProgressRing),
null);

public static readonly DependencyProperty TemplateSettingsProperty =
TemplateSettingsPropertyKey.DependencyProperty;

private static void OnIsActiveChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
public ProgressRingTemplateSettings TemplateSettings
{
((ProgressRing)d).ChangeVisualState(true);
get => (ProgressRingTemplateSettings)GetValue(TemplateSettingsProperty);
}

#endregion

public ProgressRingTemplateSettings TemplateSettings { get; }
protected override AutomationPeer OnCreateAutomationPeer()
{
return new ProgressRingAutomationPeer(this);
}

public override void OnApplyTemplate()
{
base.OnApplyTemplate();

ChangeVisualState(false);
ChangeVisualState();
}

protected override void OnRenderSizeChanged(SizeChangedInfo sizeInfo)
void OnSizeChanged(object sender, SizeChangedEventArgs e)
{
base.OnRenderSizeChanged(sizeInfo);

double maxSideLength = Math.Min(sizeInfo.NewSize.Width, sizeInfo.NewSize.Height);
double ellipseDiameter = 0.1 * maxSideLength;
if (maxSideLength <= 40)
{
ellipseDiameter += 1;
}
ApplyTemplateSettings();
ChangeVisualState();
}

var templateSettings = TemplateSettings;
templateSettings.EllipseDiameter = ellipseDiameter;
templateSettings.EllipseOffset = new Thickness(0, maxSideLength / 2 - ellipseDiameter, 0, 0);
templateSettings.MaxSideLength = maxSideLength;
void OnIsActivePropertyChanged(DependencyPropertyChangedEventArgs args)
{
ChangeVisualState();
}

ChangeVisualState(true);
void ChangeVisualState()
{
VisualStateManager.GoToState(this, IsActive ? s_ActiveStateName : s_InactiveStateName, true);
VisualStateManager.GoToState(this, TemplateSettings.MaxSideLength < 60 ? s_SmallStateName : s_LargeStateName, true);
}

private void ChangeVisualState(bool useTransitions)
void ApplyTemplateSettings()
{
VisualStateManager.GoToState(this, IsActive ? ActiveState : InactiveState, useTransitions);
VisualStateManager.GoToState(this, TemplateSettings.MaxSideLength < 60 ? SmallState : LargeState, useTransitions);
// TemplateSetting properties from WUXC for backwards compatibility.
var templateSettings = TemplateSettings;

var (width, diameterValue, anchorPoint) = calcSettings();
(double, double, double) calcSettings()
{
if (ActualWidth != 0)
{
double width = Math.Min(ActualWidth, ActualHeight);

double diameterAdditive;
{
double init()
{
if (width <= 40.0)
{
return 1.0;
}
return 0.0;
}
diameterAdditive = init();
}

double diamaterValue = (width * 0.1) + diameterAdditive;
double anchorPoint = (width * 0.5) - diamaterValue;
return (width, diamaterValue, anchorPoint);
}

return (0.0, 0.0, 0.0);
};

templateSettings.EllipseDiameter = diameterValue;

Thickness thicknessEllipseOffset = new Thickness(0, anchorPoint, 0, 0);

templateSettings.EllipseOffset = thicknessEllipseOffset;
templateSettings.MaxSideLength = width;
}
}
}
3 changes: 2 additions & 1 deletion ModernWpf.Controls/ProgressRing/ProgressRing.xaml
Expand Up @@ -7,12 +7,13 @@

<Style TargetType="local:ProgressRing">
<Setter Property="Background" Value="Transparent" />
<Setter Property="Foreground" Value="{DynamicResource SystemControlHighlightAccentBrush}" />
<Setter Property="Foreground" Value="{DynamicResource ProgressRingForegroundThemeBrush}" />
<Setter Property="IsHitTestVisible" Value="False" />
<Setter Property="HorizontalAlignment" Value="Center" />
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="MinHeight" Value="20" />
<Setter Property="MinWidth" Value="20" />
<Setter Property="IsTabStop" Value="False" />
<Setter Property="Focusable" Value="False" />
<Setter Property="Template">
<Setter.Value>
Expand Down
Expand Up @@ -4,6 +4,12 @@ namespace ModernWpf.Controls.Primitives
{
public sealed class ProgressRingTemplateSettings : DependencyObject
{
internal ProgressRingTemplateSettings()
{
}

// TemplateSetting properties from WUXC for backwards compatibility.

#region EllipseDiameter

private static readonly DependencyPropertyKey EllipseDiameterPropertyKey =
Expand Down
29 changes: 26 additions & 3 deletions ModernWpf/ProgressBar/ProgressBar.cs
Expand Up @@ -219,7 +219,7 @@ private void OnSizeChanged(object sender, SizeChangedEventArgs e)
{
SetProgressBarIndicatorWidth();
UpdateWidthBasedTemplateSettings();
RestartIndeterminateStoryboard();
ReapplyIndeterminateStoryboard();
}

protected override void OnValueChanged(double oldValue, double newValue)
Expand Down Expand Up @@ -249,7 +249,7 @@ private void OnIsIndeterminatePropertyChanged(DependencyPropertyChangedEventArgs
{
SetProgressBarIndicatorWidth();
UpdateStates();
RestartIndeterminateStoryboard();
ReapplyIndeterminateStoryboard();
}

private void OnShowPausedPropertyChanged(DependencyPropertyChangedEventArgs args)
Expand Down Expand Up @@ -391,6 +391,29 @@ private void UpdateWidthBasedTemplateSettings()
}

templateSettings.ClipRect = rectangle;

// TemplateSetting properties from WUXC for backwards compatibility.
templateSettings.EllipseAnimationEndPosition = (1.0 / 3.0) * width;
templateSettings.EllipseAnimationWellPosition = (2.0 / 3.0) * width;

if (width <= 180.0)
{
// Small ellipse diameter and offset.
templateSettings.EllipseDiameter = 4.0;
templateSettings.EllipseOffset = 4.0;
}
else if (width <= 280.0)
{
// Medium ellipse diameter and offset.
templateSettings.EllipseDiameter = 5.0;
templateSettings.EllipseOffset = 7.0;
}
else
{
// Large ellipse diameter and offset.
templateSettings.EllipseDiameter = 6.0;
templateSettings.EllipseOffset = 9.0;
}
}

private static object CoerceBrush(DependencyObject d, object baseValue)
Expand All @@ -415,7 +438,7 @@ private void RefreshStates()
UpdateStates(false);
}

private void RestartIndeterminateStoryboard()
private void ReapplyIndeterminateStoryboard()
{
Dispatcher.BeginInvoke(
() =>
Expand Down

0 comments on commit 7bd16ce

Please sign in to comment.