Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 49 additions & 0 deletions MainDemo.Wpf/RatingBar.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,55 @@
VerticalAlignment="Top"
Text="{Binding ElementName=CustomRatingBarFractionalPreview, Path=Value, StringFormat=Rating: {0}}" />
</StackPanel>

<TextBlock Style="{StaticResource MaterialDesignHeadline5TextBlock}" Text="Rating bar with preview, fractional values, and InvertDirection=true" />

<StackPanel Margin="0,16,0,0" Orientation="Horizontal">
<smtx:XamlDisplay Margin="5,0,0,5"
VerticalContentAlignment="Top"
UniqueKey="fractionalPreviewRatingBar_3">
<materialDesign:RatingBar x:Name="BasicRatingBarFractionalPreview2"
IsPreviewValueEnabled="True"
Max="5"
Min="0"
InvertDirection="True"
ValueIncrements="0.25"
Value="0" />
</smtx:XamlDisplay>

<TextBlock Margin="10,2,0,0"
VerticalAlignment="Top"
Text="{Binding ElementName=BasicRatingBarFractionalPreview2, Path=Value, StringFormat=Rating: {0}}" />

<smtx:XamlDisplay Margin="24,0,0,5" UniqueKey="fractionalPreviewRatingBar_4">
<materialDesign:RatingBar x:Name="CustomRatingBarFractionalPreview2"
IsPreviewValueEnabled="True"
Max="3"
Min="0"
Orientation="Vertical"
InvertDirection="True"
ValueIncrements="0.25"
Value="2">
<materialDesign:RatingBar.ValueItemTemplate>
<DataTemplate DataType="system:Int32">
<Grid>
<materialDesign:PackIcon Width="24"
Height="24"
Kind="Heart" />
<TextBlock HorizontalAlignment="Center"
VerticalAlignment="Center"
FontSize="8"
Foreground="{DynamicResource PrimaryHueMidForegroundBrush}"
Text="{Binding}" />
</Grid>
</DataTemplate>
</materialDesign:RatingBar.ValueItemTemplate>
</materialDesign:RatingBar>
</smtx:XamlDisplay>
<TextBlock Margin="10,2,0,0"
VerticalAlignment="Top"
Text="{Binding ElementName=CustomRatingBarFractionalPreview2, Path=Value, StringFormat=Rating: {0}}" />
</StackPanel>
</StackPanel>
</UserControl>

67 changes: 47 additions & 20 deletions MaterialDesignThemes.Wpf.Tests/RatingBarTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,29 @@ public void TextBlockForegroundConverter_ShouldReturnFractionalGradientStops_Whe
Assert.Equal(brush.Color.WithAlphaChannel(RatingBar.TextBlockForegroundConverter.SemiTransparent), stop2.Color);
}

[Fact]
public void TextBlockForegroundConverter_ShouldReturnFractionalGradientStops_WhenValueCovers10PercentOfButtonValueAndDirectionIsInverted()
{
// Arrange
SolidColorBrush brush = Brushes.Red;
IMultiValueConverter converter = RatingBar.TextBlockForegroundConverter.Instance;
object[] values = Arrange_TextBlockForegroundConverterValues(brush, value: 1.1, buttonValue: 2, invertDirection: true);

// Act
var result = converter.Convert(values, typeof(Brush), null, CultureInfo.CurrentCulture) as Brush;

// Assert
Assert.IsAssignableFrom<LinearGradientBrush>(result);
LinearGradientBrush resultBrush = (LinearGradientBrush)result!;
Assert.Equal(2, resultBrush.GradientStops.Count);
GradientStop stop1 = resultBrush.GradientStops[0];
GradientStop stop2 = resultBrush.GradientStops[1];
Assert.Equal(0.9, stop1.Offset, 10);
Assert.Equal(brush.Color.WithAlphaChannel(RatingBar.TextBlockForegroundConverter.SemiTransparent), stop1.Color);
Assert.Equal(0.9, stop2.Offset, 10);
Assert.Equal(brush.Color, stop2.Color);
}

[Fact]
public void TextBlockForegroundConverter_ShouldReturnFractionalGradientStops_WhenValueCovers42PercentOfButtonValue()
{
Expand Down Expand Up @@ -277,15 +300,15 @@ public void TextBlockForegroundConverter_ShouldReturnFractionalGradientStops_Whe
Assert.Equal(brush.Color.WithAlphaChannel(RatingBar.TextBlockForegroundConverter.SemiTransparent), stop2.Color);
}

private static object[] Arrange_TextBlockForegroundConverterValues(SolidColorBrush brush, double value, int buttonValue, Orientation orientation = Orientation.Horizontal) =>
new object[] { brush, orientation, value, buttonValue };
private static object[] Arrange_TextBlockForegroundConverterValues(SolidColorBrush brush, double value, int buttonValue, Orientation orientation = Orientation.Horizontal, bool invertDirection = false) =>
new object[] { brush, orientation, invertDirection, value, buttonValue };

[Fact]
public void PreviewIndicatorTransformXConverter_ShouldCenterPreviewIndicator_WhenFractionalValuesAreDisabledAndOrientationIsHorizontal()
{
// Arrange
IMultiValueConverter converter = RatingBar.PreviewIndicatorTransformXConverter.Instance;
object[] values = Arrange_PreviewIndicatorTransformXConverterValues(100, 20, Orientation.Horizontal, false, 1, 1);
object[] values = Arrange_PreviewIndicatorTransformXConverterValues(100, 20, Orientation.Horizontal, false, false, 1, 1);

// Act
double? result = converter.Convert(values, typeof(double), null, CultureInfo.CurrentCulture) as double?;
Expand All @@ -295,27 +318,29 @@ public void PreviewIndicatorTransformXConverter_ShouldCenterPreviewIndicator_Whe
Assert.Equal(40.0, result); // 50% of 100 minus 20/2
}

[Fact]
public void PreviewIndicatorTransformXConverter_ShouldOffsetPreviewIndicatorByPercentage_WhenFractionalValuesAreEnabledAndOrientationIsHorizontal()
[Theory]
[InlineData(false, 15.0)] // 25% of 100 minus 20/2
[InlineData(true, 65.0)] // 75% of 100 minus 20/2
public void PreviewIndicatorTransformXConverter_ShouldOffsetPreviewIndicatorByPercentage_WhenFractionalValuesAreEnabledAndOrientationIsHorizontal(bool invertDirection, double expectedValue)
{
// Arrange
IMultiValueConverter converter = RatingBar.PreviewIndicatorTransformXConverter.Instance;
object[] values = Arrange_PreviewIndicatorTransformXConverterValues(100, 20, Orientation.Horizontal, true, 1.25, 1);
object[] values = Arrange_PreviewIndicatorTransformXConverterValues(100, 20, Orientation.Horizontal, invertDirection, true, 1.25, 1);

// Act
double? result = converter.Convert(values, typeof(double), null, CultureInfo.CurrentCulture) as double?;

// Assert
Assert.NotNull(result);
Assert.Equal(15.0, result); // 25% of 100 minus 20/2
Assert.Equal(expectedValue, result);
}

[Fact]
public void PreviewIndicatorTransformXConverter_ShouldPlacePreviewIndicatorWithSmallMargin_WhenFractionalValuesAreDisabledAndOrientationIsVertical()
{
// Arrange
IMultiValueConverter converter = RatingBar.PreviewIndicatorTransformXConverter.Instance;
object[] values = Arrange_PreviewIndicatorTransformXConverterValues(100, 20, Orientation.Vertical, false, 1, 1);
object[] values = Arrange_PreviewIndicatorTransformXConverterValues(100, 20, Orientation.Vertical, false, false, 1, 1);
double expectedValue = -20 - RatingBar.PreviewIndicatorTransformXConverter.Margin;

// Act
Expand All @@ -331,7 +356,7 @@ public void PreviewIndicatorTransformXConverter_ShouldPlacePreviewIndicatorWithS
{
// Arrange
IMultiValueConverter converter = RatingBar.PreviewIndicatorTransformXConverter.Instance;
object[] values = Arrange_PreviewIndicatorTransformXConverterValues(100, 20, Orientation.Vertical, true, 1.25, 1);
object[] values = Arrange_PreviewIndicatorTransformXConverterValues(100, 20, Orientation.Vertical, false, true, 1.25, 1);
double expectedValue = -20 - RatingBar.PreviewIndicatorTransformXConverter.Margin;

// Act
Expand All @@ -344,15 +369,15 @@ public void PreviewIndicatorTransformXConverter_ShouldPlacePreviewIndicatorWithS



private static object[] Arrange_PreviewIndicatorTransformXConverterValues(double ratingBarButtonActualWidth, double previewValueActualWidth, Orientation orientation, bool isFractionalValueEnabled, double previewValue, int buttonValue) =>
new object[] { ratingBarButtonActualWidth, previewValueActualWidth, orientation, isFractionalValueEnabled, previewValue, buttonValue };
private static object[] Arrange_PreviewIndicatorTransformXConverterValues(double ratingBarButtonActualWidth, double previewValueActualWidth, Orientation orientation, bool invertDirection, bool isFractionalValueEnabled, double previewValue, int buttonValue) =>
new object[] { ratingBarButtonActualWidth, previewValueActualWidth, orientation, invertDirection, isFractionalValueEnabled, previewValue, buttonValue };

[Fact]
public void PreviewIndicatorTransformYConverter_ShouldPlacePreviewIndicatorWithSmallMargin_WhenFractionalValuesAreDisabledAndOrientationIsHorizontal()
{
// Arrange
IMultiValueConverter converter = RatingBar.PreviewIndicatorTransformYConverter.Instance;
object[] values = Arrange_PreviewIndicatorTransformYConverterValues(100, 20, Orientation.Horizontal, false, 1, 1);
object[] values = Arrange_PreviewIndicatorTransformYConverterValues(100, 20, Orientation.Horizontal, false, false, 1, 1);
double expectedValue = -20 - RatingBar.PreviewIndicatorTransformYConverter.Margin;

// Act
Expand All @@ -368,7 +393,7 @@ public void PreviewIndicatorTransformYConverter_ShouldPlacePreviewIndicatorWithS
{
// Arrange
IMultiValueConverter converter = RatingBar.PreviewIndicatorTransformYConverter.Instance;
object[] values = Arrange_PreviewIndicatorTransformYConverterValues(100, 20, Orientation.Horizontal, true, 1.25, 1);
object[] values = Arrange_PreviewIndicatorTransformYConverterValues(100, 20, Orientation.Horizontal, false, true, 1.25, 1);
double expectedValue = -20 - RatingBar.PreviewIndicatorTransformYConverter.Margin;

// Act
Expand All @@ -384,7 +409,7 @@ public void PreviewIndicatorTransformYConverter_ShouldCenterPreviewIndicator_Whe
{
// Arrange
IMultiValueConverter converter = RatingBar.PreviewIndicatorTransformYConverter.Instance;
object[] values = Arrange_PreviewIndicatorTransformYConverterValues(100, 20, Orientation.Vertical, false, 1, 1);
object[] values = Arrange_PreviewIndicatorTransformYConverterValues(100, 20, Orientation.Vertical, false, false, 1, 1);

// Act
double? result = converter.Convert(values, typeof(double), null, CultureInfo.CurrentCulture) as double?;
Expand All @@ -394,23 +419,25 @@ public void PreviewIndicatorTransformYConverter_ShouldCenterPreviewIndicator_Whe
Assert.Equal(40.0, result); // 50% of 100 minus 20/2
}

[Fact]
public void PreviewIndicatorTransformYConverter_ShouldPreviewIndicatorByPercentage_WhenFractionalValuesAreEnabledAndOrientationIsVertical()
[Theory]
[InlineData(false, 15.0)] // 25% of 100 minus 20/2
[InlineData(true, 65.0)] // 75% of 100 minus 20/2
public void PreviewIndicatorTransformYConverter_ShouldPreviewIndicatorByPercentage_WhenFractionalValuesAreEnabledAndOrientationIsVertical(bool invertDirection, double expectedValue)
{
// Arrange
IMultiValueConverter converter = RatingBar.PreviewIndicatorTransformYConverter.Instance;
object[] values = Arrange_PreviewIndicatorTransformYConverterValues(100, 20, Orientation.Vertical, true, 1.25, 1);
object[] values = Arrange_PreviewIndicatorTransformYConverterValues(100, 20, Orientation.Vertical, invertDirection, true, 1.25, 1);

// Act
double? result = converter.Convert(values, typeof(double), null, CultureInfo.CurrentCulture) as double?;

// Assert
Assert.NotNull(result);
Assert.Equal(15.0, result); // 25% of 100 minus 20/2
Assert.Equal(expectedValue, result);
}

private static object[] Arrange_PreviewIndicatorTransformYConverterValues(double ratingBarButtonActualHeight, double previewValueActualHeight, Orientation orientation, bool isFractionalValueEnabled, double previewValue, int buttonValue) =>
new object[] { ratingBarButtonActualHeight, previewValueActualHeight, orientation, isFractionalValueEnabled, previewValue, buttonValue };
private static object[] Arrange_PreviewIndicatorTransformYConverterValues(double ratingBarButtonActualHeight, double previewValueActualHeight, Orientation orientation, bool invertDirection, bool isFractionalValueEnabled, double previewValue, int buttonValue) =>
new object[] { ratingBarButtonActualHeight, previewValueActualHeight, orientation, invertDirection, isFractionalValueEnabled, previewValue, buttonValue };
}

internal static class ColorExtensions
Expand Down
Loading