diff --git a/maui/src/EffectsView/SfEffectsView.cs b/maui/src/EffectsView/SfEffectsView.cs index 5b2cb9e6..3732216b 100644 --- a/maui/src/EffectsView/SfEffectsView.cs +++ b/maui/src/EffectsView/SfEffectsView.cs @@ -1512,7 +1512,7 @@ void RemoveHighlightEffect() /// The touch point. void AddResetEffects(AutoResetEffects effects, Point touchPoint) { - foreach (var effect in effects.GetAllAutoResetEffectsItems().Select(v => (AutoResetEffects)v)) + foreach (AutoResetEffects effect in effects.GetAllAutoResetEffectsItems()) { if (effect == AutoResetEffects.None) { @@ -1544,7 +1544,7 @@ void AddResetEffects(AutoResetEffects effects, Point touchPoint) /// The touch point. void AddEffects(SfEffects sfEffect, Point touchPoint) { - foreach (SfEffects effect in sfEffect.GetAllItems().Select(v => (SfEffects)v)) + foreach (SfEffects effect in sfEffect.GetAllItems()) { if (effect == SfEffects.None) { diff --git a/maui/src/EffectsView/Utils.cs b/maui/src/EffectsView/Utils.cs index 7f909e11..9593d951 100644 --- a/maui/src/EffectsView/Utils.cs +++ b/maui/src/EffectsView/Utils.cs @@ -10,32 +10,32 @@ internal static partial class FlaggedEnumExt /// /// Target enum. /// Available enum values. - internal static IEnumerable GetAllItems(this SfEffects targetEnum) + internal static IEnumerable GetAllItems(this SfEffects targetEnum) { - foreach (Enum value in Enum.GetValues()) + foreach (SfEffects value in Enum.GetValues()) { //// If the flag value of the enum is zero, then the HasFlag method always returns true. Hence, the None is returned only if the value and the target enum is equals to None. - if (value.ToString() != "None" && targetEnum.HasFlag(value)) + if (value != SfEffects.None && targetEnum.HasFlag(value)) { yield return value; } - else if (value.ToString() == "None" && targetEnum.Equals(value)) + else if (value == SfEffects.None && targetEnum == SfEffects.None) { yield return value; } } } - internal static IEnumerable GetAllAutoResetEffectsItems(this AutoResetEffects targetEnum) + internal static IEnumerable GetAllAutoResetEffectsItems(this AutoResetEffects targetEnum) { - foreach (Enum value in Enum.GetValues()) + foreach (AutoResetEffects value in Enum.GetValues()) { //// If the flag value of the enum is zero, then the HasFlag method always returns true. Hence, the None is returned only if the value and the target enum is equals to None. - if (value.ToString() != "None" && targetEnum.HasFlag(value)) + if (value != AutoResetEffects.None && targetEnum.HasFlag(value)) { yield return value; } - else if (value.ToString() == "None" && targetEnum.Equals(value)) + else if (value == AutoResetEffects.None && targetEnum == AutoResetEffects.None) { yield return value; } diff --git a/maui/src/Picker/Helper/DatePickerHelper.cs b/maui/src/Picker/Helper/DatePickerHelper.cs index b5ab2d54..52bc8e99 100644 --- a/maui/src/Picker/Helper/DatePickerHelper.cs +++ b/maui/src/Picker/Helper/DatePickerHelper.cs @@ -857,8 +857,9 @@ static List GetCustomFormatOrder(string cultureDateFormat, out string dayFo } } - // Distinct Method is used to store only unique values in the list. - formatOrder = formatOrder.Distinct().ToList(); + // Remove duplicates without LINQ allocation by using a seen set. + var seen = new HashSet(); + formatOrder.RemoveAll(x => !seen.Add(x)); return formatOrder; } diff --git a/maui/src/Picker/Helper/TimePickerHelper.cs b/maui/src/Picker/Helper/TimePickerHelper.cs index c18500f3..d99aea0e 100644 --- a/maui/src/Picker/Helper/TimePickerHelper.cs +++ b/maui/src/Picker/Helper/TimePickerHelper.cs @@ -632,8 +632,9 @@ static List GetCustomFormatOrder(string cultureTimeFormat, out string hourF } } - // Distinct method is used to store only unique values in the list - formatOrder = formatOrder.Distinct().ToList(); + // Remove duplicates without LINQ allocation by using a seen set. + var seen = new HashSet(); + formatOrder.RemoveAll(x => !seen.Add(x)); return formatOrder; } diff --git a/maui/src/ProgressBar/Utility/Utility.cs b/maui/src/ProgressBar/Utility/Utility.cs index 3fc88494..c7ef7ae3 100644 --- a/maui/src/ProgressBar/Utility/Utility.cs +++ b/maui/src/ProgressBar/Utility/Utility.cs @@ -95,22 +95,24 @@ internal static double CornerRadiusAngle(double radius, double circleRadius) /// Updated gradient stops collection. internal static List UpdateGradientStopCollection(List gradientStops, double rangeStart, double rangeEnd) { - gradientStops = gradientStops.OrderBy(x => x.ActualValue).ToList(); + gradientStops.Sort((a, b) => a.ActualValue.CompareTo(b.ActualValue)); - if (gradientStops.First().ActualValue > rangeStart) + var firstStop = gradientStops[0]; + if (firstStop.ActualValue > rangeStart) { gradientStops.Insert(0, new ProgressGradientStop { - Color = gradientStops.First().Color, + Color = firstStop.Color, ActualValue = rangeStart }); } - if (gradientStops.Last().ActualValue < rangeEnd) + var lastStop = gradientStops[gradientStops.Count - 1]; + if (lastStop.ActualValue < rangeEnd) { gradientStops.Add(new ProgressGradientStop { - Color = gradientStops.Last().Color, + Color = lastStop.Color, ActualValue = rangeEnd }); } diff --git a/maui/src/SegmentedControl/Views/SegmentLayout.cs b/maui/src/SegmentedControl/Views/SegmentLayout.cs index 06608db4..46300e4c 100644 --- a/maui/src/SegmentedControl/Views/SegmentLayout.cs +++ b/maui/src/SegmentedControl/Views/SegmentLayout.cs @@ -61,7 +61,15 @@ internal SegmentLayout(ISegmentItemInfo itemInfo) internal void UpdateItemSelection() { int selectedIndex = GetSelectedIndex(); - SegmentItemView? olditemView = Children.OfType().FirstOrDefault(x => x._isSelected); + SegmentItemView? olditemView = null; + foreach (var child in Children) + { + if (child is SegmentItemView siv && siv._isSelected) + { + olditemView = siv; + break; + } + } SegmentItemView? newitemView = GetSegmentItemView(selectedIndex); olditemView?.ClearSelection(); @@ -667,11 +675,11 @@ void OnSegmentItemPropertyChanged(object? sender, System.ComponentModel.Property // Ticket-533501- Change the image source when item is selected. if (propertyName == nameof(SfSegmentItem.ImageSource)) { - foreach (SegmentItemView child in Children.Cast()) + foreach (var child in Children) { - if (child._segmentItem.Equals(segmentItem)) + if (child is SegmentItemView segmentItemView && segmentItemView._segmentItem.Equals(segmentItem)) { - child.UpdateImageView(); + segmentItemView.UpdateImageView(); break; } } diff --git a/maui/src/SparkCharts/SfSparkAreaChart.cs b/maui/src/SparkCharts/SfSparkAreaChart.cs index 545d1996..3a38d053 100644 --- a/maui/src/SparkCharts/SfSparkAreaChart.cs +++ b/maui/src/SparkCharts/SfSparkAreaChart.cs @@ -245,28 +245,32 @@ internal override void OnDraw(ICanvas canvas, Rect rect) var _segments = CreateSegments(rect, _baselineY); foreach (var segment in _segments) { - if (segment.Count < 1) + int segmentCount = segment.Count; + if (segmentCount < 1) { continue; } + var firstPoint = segment[0]; + var lastPoint = segment[segmentCount - 1]; + // Create the filled area path for the segment. var _areaPath = new PathF(); - _areaPath.MoveTo(segment.First().X, _baselineY); + _areaPath.MoveTo(firstPoint.X, _baselineY); foreach (var point in segment) { _areaPath.LineTo(point); } - _areaPath.LineTo(segment.Last().X, _baselineY); + _areaPath.LineTo(lastPoint.X, _baselineY); _areaPath.Close(); canvas.SetFillPaint(Fill, _areaPath.Bounds); canvas.FillPath(_areaPath); // Create and draw the stroke path along the top of the area. - var _strokePath = new PathF(segment.First()); - for (int i = 1; i < segment.Count; i++) + var _strokePath = new PathF(firstPoint); + for (int i = 1; i < segmentCount; i++) { _strokePath.LineTo(segment[i]); } diff --git a/maui/tests/Syncfusion.Maui.Toolkit.UnitTest/Miscellaneous/EffectsViewUtilsUnitTests.cs b/maui/tests/Syncfusion.Maui.Toolkit.UnitTest/Miscellaneous/EffectsViewUtilsUnitTests.cs new file mode 100644 index 00000000..07830131 --- /dev/null +++ b/maui/tests/Syncfusion.Maui.Toolkit.UnitTest/Miscellaneous/EffectsViewUtilsUnitTests.cs @@ -0,0 +1,74 @@ +using Syncfusion.Maui.Toolkit.EffectsView; +using Xunit; + +namespace Syncfusion.Maui.Toolkit.UnitTest +{ + public class EffectsViewUtilsUnitTests + { + #region GetAllItems Tests + + [Fact] + public void GetAllItems_ReturnsNone_WhenEnumIsNone() + { + var result = SfEffects.None.GetAllItems().ToList(); + + Assert.Single(result); + Assert.Equal(SfEffects.None, result[0]); + } + + [Fact] + public void GetAllItems_ReturnsSingleFlag_WhenSingleFlagSet() + { + var result = SfEffects.Ripple.GetAllItems().ToList(); + + Assert.Single(result); + Assert.Equal(SfEffects.Ripple, result[0]); + } + + [Fact] + public void GetAllItems_ReturnsMultipleFlags_WhenCombinedFlags() + { + var effects = SfEffects.Ripple | SfEffects.Highlight; + var result = effects.GetAllItems().ToList(); + + Assert.Contains(SfEffects.Ripple, result); + Assert.Contains(SfEffects.Highlight, result); + Assert.DoesNotContain(SfEffects.None, result); + } + + #endregion + + #region GetAllAutoResetEffectsItems Tests + + [Fact] + public void GetAllAutoResetEffectsItems_ReturnsNone_WhenEnumIsNone() + { + var result = AutoResetEffects.None.GetAllAutoResetEffectsItems().ToList(); + + Assert.Single(result); + Assert.Equal(AutoResetEffects.None, result[0]); + } + + [Fact] + public void GetAllAutoResetEffectsItems_ReturnsSingleFlag_WhenSingleFlagSet() + { + var result = AutoResetEffects.Ripple.GetAllAutoResetEffectsItems().ToList(); + + Assert.Single(result); + Assert.Equal(AutoResetEffects.Ripple, result[0]); + } + + [Fact] + public void GetAllAutoResetEffectsItems_ReturnsMultipleFlags_WhenCombinedFlags() + { + var effects = AutoResetEffects.Ripple | AutoResetEffects.Highlight; + var result = effects.GetAllAutoResetEffectsItems().ToList(); + + Assert.Contains(AutoResetEffects.Ripple, result); + Assert.Contains(AutoResetEffects.Highlight, result); + Assert.DoesNotContain(AutoResetEffects.None, result); + } + + #endregion + } +} diff --git a/maui/tests/Syncfusion.Maui.Toolkit.UnitTest/ProgressBar/ProgressBarUtilityUnitTests.cs b/maui/tests/Syncfusion.Maui.Toolkit.UnitTest/ProgressBar/ProgressBarUtilityUnitTests.cs new file mode 100644 index 00000000..76e12461 --- /dev/null +++ b/maui/tests/Syncfusion.Maui.Toolkit.UnitTest/ProgressBar/ProgressBarUtilityUnitTests.cs @@ -0,0 +1,92 @@ +using Microsoft.Maui.Graphics; +using Syncfusion.Maui.Toolkit.ProgressBar; +using Xunit; + +namespace Syncfusion.Maui.Toolkit.UnitTest +{ + public class ProgressBarUtilityUnitTests + { + #region UpdateGradientStopCollection Tests + + [Fact] + public void UpdateGradientStopCollection_SortsStopsByActualValue() + { + var stops = new List + { + new ProgressGradientStop { Color = Colors.Red, ActualValue = 70 }, + new ProgressGradientStop { Color = Colors.Green, ActualValue = 30 }, + new ProgressGradientStop { Color = Colors.Blue, ActualValue = 50 }, + }; + + var result = Utility.UpdateGradientStopCollection(stops, 0, 100); + + Assert.True(result[0].ActualValue <= result[1].ActualValue); + Assert.True(result[1].ActualValue <= result[2].ActualValue); + } + + [Fact] + public void UpdateGradientStopCollection_InsertsStopAtStart_WhenFirstExceedsRangeStart() + { + var stops = new List + { + new ProgressGradientStop { Color = Colors.Red, ActualValue = 30 }, + new ProgressGradientStop { Color = Colors.Blue, ActualValue = 70 }, + }; + + var result = Utility.UpdateGradientStopCollection(stops, 0, 100); + + // Both start and end are inserted since 30 > 0 and 70 < 100 + Assert.Equal(4, result.Count); + Assert.Equal(0, result[0].ActualValue); + Assert.Equal(Colors.Red, result[0].Color); + } + + [Fact] + public void UpdateGradientStopCollection_AppendsStopAtEnd_WhenLastBelowRangeEnd() + { + var stops = new List + { + new ProgressGradientStop { Color = Colors.Red, ActualValue = 30 }, + new ProgressGradientStop { Color = Colors.Blue, ActualValue = 70 }, + }; + + var result = Utility.UpdateGradientStopCollection(stops, 0, 100); + + // Both start and end are inserted since 30 > 0 and 70 < 100 + Assert.Equal(4, result.Count); + Assert.Equal(100, result[result.Count - 1].ActualValue); + Assert.Equal(Colors.Blue, result[result.Count - 1].Color); + } + + [Fact] + public void UpdateGradientStopCollection_DoesNotInsert_WhenStopsAlreadyCoverRange() + { + var stops = new List + { + new ProgressGradientStop { Color = Colors.Red, ActualValue = 0 }, + new ProgressGradientStop { Color = Colors.Blue, ActualValue = 100 }, + }; + + var result = Utility.UpdateGradientStopCollection(stops, 0, 100); + + Assert.Equal(2, result.Count); + } + + [Fact] + public void UpdateGradientStopCollection_InsertsAtBothEnds_WhenStopsDoNotCoverRange() + { + var stops = new List + { + new ProgressGradientStop { Color = Colors.Green, ActualValue = 50 }, + }; + + var result = Utility.UpdateGradientStopCollection(stops, 0, 100); + + Assert.Equal(3, result.Count); + Assert.Equal(0, result[0].ActualValue); + Assert.Equal(100, result[result.Count - 1].ActualValue); + } + + #endregion + } +}