22// The .NET Foundation licenses this file to you under the MIT license.
33// See the LICENSE file in the project root for more information.
44
5- using System ;
6- using System . Collections . Generic ;
7- using System . Linq ;
8- using System . Text ;
9- using System . Threading . Tasks ;
5+ using System . Collections ;
6+ using System . Drawing ;
7+ using Microsoft . Toolkit . Diagnostics ;
108
119namespace Microsoft . Toolkit . Uwp . UI . Controls
1210{
@@ -16,23 +14,81 @@ namespace Microsoft.Toolkit.Uwp.UI.Controls
1614 /// <see cref="UniformGrid.GetFreeSpot"/> iterator.
1715 /// This is used so we can better isolate our logic and make it easier to test.
1816 /// </summary>
19- internal class TakenSpotsReferenceHolder
17+ internal sealed class TakenSpotsReferenceHolder
2018 {
2119 /// <summary>
22- /// Gets or sets the array to hold taken spots.
23- /// True value indicates an item in the layout is fixed to that position.
24- /// False values indicate free openings where an item can be placed.
20+ /// The <see cref="BitArray"/> instance used to efficiently track empty spots.
2521 /// </summary>
26- public bool [ , ] SpotsTaken { get ; set ; }
22+ private readonly BitArray spotsTaken ;
2723
24+ /// <summary>
25+ /// Initializes a new instance of the <see cref="TakenSpotsReferenceHolder"/> class.
26+ /// </summary>
27+ /// <param name="rows">The number of rows to track.</param>
28+ /// <param name="columns">The number of columns to track.</param>
2829 public TakenSpotsReferenceHolder ( int rows , int columns )
2930 {
30- SpotsTaken = new bool [ rows , columns ] ;
31+ Guard . IsGreaterThanOrEqualTo ( rows , 0 , nameof ( rows ) ) ;
32+ Guard . IsGreaterThanOrEqualTo ( columns , 0 , nameof ( columns ) ) ;
33+
34+ Height = rows ;
35+ Width = columns ;
36+
37+ this . spotsTaken = new BitArray ( rows * columns ) ;
38+ }
39+
40+ /// <summary>
41+ /// Gets the height of the grid to monitor.
42+ /// </summary>
43+ public int Height { get ; }
44+
45+ /// <summary>
46+ /// Gets the width of the grid to monitor.
47+ /// </summary>
48+ public int Width { get ; }
49+
50+ /// <summary>
51+ /// Gets or sets the value of a specified grid cell.
52+ /// </summary>
53+ /// <param name="i">The vertical offset.</param>
54+ /// <param name="j">The horizontal offset.</param>
55+ public bool this [ int i , int j ]
56+ {
57+ get => this . spotsTaken [ ( i * Width ) + j ] ;
58+ set => this . spotsTaken [ ( i * Width ) + j ] = value ;
59+ }
60+
61+ /// <summary>
62+ /// Fills the specified area in the current grid with a given value.
63+ /// If invalid coordinates are given, they will simply be ignored and no exception will be thrown.
64+ /// </summary>
65+ /// <param name="value">The value to fill the target area with.</param>
66+ /// <param name="row">The row to start on (inclusive, 0-based index).</param>
67+ /// <param name="column">The column to start on (inclusive, 0-based index).</param>
68+ /// <param name="width">The positive width of area to fill.</param>
69+ /// <param name="height">The positive height of area to fill.</param>
70+ public void Fill ( bool value , int row , int column , int width , int height )
71+ {
72+ Rectangle bounds = new Rectangle ( 0 , 0 , Width , Height ) ;
73+
74+ // Precompute bounds to skip branching in main loop
75+ bounds . Intersect ( new Rectangle ( column , row , width , height ) ) ;
76+
77+ for ( int i = bounds . Top ; i < bounds . Bottom ; i ++ )
78+ {
79+ for ( int j = bounds . Left ; j < bounds . Right ; j ++ )
80+ {
81+ this [ i , j ] = value ;
82+ }
83+ }
3184 }
3285
33- public TakenSpotsReferenceHolder ( bool [ , ] array )
86+ /// <summary>
87+ /// Resets the current reference holder.
88+ /// </summary>
89+ public void Reset ( )
3490 {
35- SpotsTaken = array ;
91+ this . spotsTaken . SetAll ( false ) ;
3692 }
3793 }
3894}
0 commit comments