Using a Simple Perfect Squared Square to test UWP controls

This article presents a UWP XAML control that displays 21 square UI elements, each of a different size, inside a square.

Math to the rescue

For testing the UI and the performance of some user controls, I wanted to create a square panel to host as many as possible square areas of a different size. That smells like a mathematical problem, right? And yes: I found a mathematical solution in a domain that is called squaring the square.

Allow me to introduce you to the lowest-order simple perfect squared square:

Squaring_the_square

It’s a “squared square” because … well … it’s a square made up of squares. It’s “perfect” because each of the inner squares has a different size, and it’s “simple” because no subset of inner squares forms a rectangle or square. On top of that, all of the 21 inner squares are “integral”: their side is of integer length (which is convenient for calculating coordinates).

You can devote an entire web site to this, or you can use it as a design for furniture. Personally, I think of it as a nice frame for torturing testing UI components.

Creating the Square of Squares control

So I built the SquareOfSquares, a –square- XAML UserControl that hosts a series of –square- ContentControl instances, distributed according to the simples perfect squared square pattern. On the outside, it’s a square Grid, wrapped in a ViewBox. The side of the grid is a multiple of 112, which is the side of the mathematical square. It’s a size in relative pixels, so I made it big enough (1120) to avoid rounding problems when the actual controls are drawn:

<Viewbox Stretch="Uniform">
    <Grid x:Name="Root"
            Height="1120"
            Width="1120" />
</Viewbox>

The control has a private list of instances of an –also private- InnerSquare class. This list holds the position and the side of all the inner squares:

private List<InnerSquare> GetSquares()
{
    var list = new List<InnerSquare>();

    list.Add(new InnerSquare() { Position = new Point(0, 0), Side = 50 });
    list.Add(new InnerSquare() { Position = new Point(50, 0), Side = 35 });
    list.Add(new InnerSquare() { Position = new Point(85, 0), Side = 27 });
    // more of these ...
    return list;
}

When the SquareOfSquare is created, 112 rows and columns are created, and for each of the inner squares a ContentControl is created with the relevant attached grid properties (i.e. row, column, and both spans):

for (int i = 0; i < 112; i++)
{
    Root.RowDefinitions.Add(new RowDefinition() 
    { Height = new GridLength(1, GridUnitType.Star) });
    Root.ColumnDefinitions.Add(new ColumnDefinition() 
    { Width = new GridLength(1, GridUnitType.Star) });
}

foreach (InnerSquare square in GetSquares())
{
    var ctl = new ContentControl();
    ctl.SetValue(Grid.RowProperty, square.Position.Y);
    ctl.SetValue(Grid.ColumnProperty, square.Position.X);
    ctl.SetValue(Grid.ColumnSpanProperty, square.Side);
    ctl.SetValue(Grid.RowSpanProperty, square.Side);
    Root.Children.Add(ctl);
    Squares.Add(ctl);
}

The content controls are added to the grid, but also to a Squares list, which is exposed as a property:

public List<ContentControl> Squares { get; private set; } 
           = new List<ContentControl>();

I also added some extension methods that apply to the inner squares: Side() and RandomColor():

private static Random r = new Random(DateTime.Now.Millisecond);

/// <summary>
/// Returns the side of an inner square.
/// </summary>
public static int Side(this UIElement element)
{
    return (int)element.GetValue(Grid.RowSpanProperty);
}

/// <summary>
/// Returns a random color.
/// </summary>
/// <remarks>Not necessarily an extension method. Just for convenience.</remarks>
public static Color RandomColor(this UIElement element)
{
    byte red = (byte)r.Next(0, 255);
    byte green = (byte)r.Next(0, 255);
    byte blue = (byte)r.Next(0, 255);

    return new Color() { A = 255, R = red, G = green, B = blue };
}

Feel free to add similar methods to return the position of the square, if you require.

Using the Square of Squares control

To use the control, drop it on a page, and give it a name:

<controls:SquareOfSquares x:Name="SquareOfSquares"
                            Margin="20" />

To populate the inner squares, iterate through the Squares collection, create your UI element, and set it as Content of the inner square. The following code snippet creates a grid with a random background color, that displays the length of the side of the square in its upper left corner:

foreach (var square in SquareOfSquares.Squares)
{
    var grid = new Grid() 
    { Height = square.ActualHeight, Width = square.ActualWidth };
    grid.Background = new SolidColorBrush(square.RandomColor());
    var side = square.Side().ToString();
    grid.Children.Add(new TextBlock() 
    { Text = side, Margin = new Thickness(2.0, 1.0, 0.0, 0.0), 
       Foreground = new SolidColorBrush(Colors.White) });
    square.Content = grid;
}

Here’s how that looks like:

SquareColors

Here’s the code to add a Radial Gauge control (from NuGet) to each of the squares:

foreach (var square in SquareOfSquares.Squares)
{
    var gauge = new Gauge() 
    { Height = square.ActualHeight, Width = square.ActualWidth };
    gauge.TrailBrush = new SolidColorBrush(square.RandomColor());
    gauge.TickBrush = new SolidColorBrush(Colors.Transparent);
    gauge.ScaleTickBrush = new SolidColorBrush(Colors.LemonChiffon);
    gauge.NeedleBrush = new SolidColorBrush(Colors.OrangeRed);
    gauge.Maximum = 50;
    var side = square.Side();
    gauge.Value = side;
    square.Content = gauge;
}

This is the result:

SquareGauges

And here’s the very straightforward code to add a Composition API Clock control:

foreach (var square in SquareOfSquares.Squares)
{
    var clock = new Clock() 
    { Height = square.ActualHeight, Width = square.ActualWidth };
    square.Content = clock;
}

This code results in a simple perfect squared square of ticking clocks:

SquareClocks

Here’s how these three examples look like on a Windows Phone:

SquareColors_Phone SquareGauges_Phone SquareClocks_Phone

Source Code

The sample app, together with the SquareOfSquares control, lives here on GitHub. The control is in its own project, ready for use.

Enjoy!

Advertisements

One thought on “Using a Simple Perfect Squared Square to test UWP controls

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s