Files
LlamaCasty/ytLive.Tests/GeometryFieldWidthTests.cs
T
gramps ef52508b1e TASK 61 + 62: the geometry fields share one width, and the border field names its colour
The creator (2026-10-21), on Live -> Layers -> webcam -> Properties:

  "the Y and H boxes under webcam properties should be the same width as the X and W
   boxes and those widths should be fixed to accomodate the max number of possible
   digits providing the geometry values"

  "also the border color drop drown box content should also include the name of the
   color next to the hex value as they in the drop-down list box"

TASK 61 - one fixed width for the four geometry fields.
The row is a DockPanel, and WPF sizes an element to its CONTENT unless it is told
otherwise, while the LAST child of a DockPanel fills the remaining space. So X/W (not
last) were as wide as their text and Y/H (last) stretched across the row - two widths
for the same kind of field. Now all four carry Width="44" and the rows set
LastChildFill="False" (without it the last field ignores its own Width and fills anyway).
44px is the measured width of "-1920" in the app's font at 11px (the largest geometry
value - the master frame is 1920x1080 - plus a sign) plus the field's padding and
border. Docs: https://learn.microsoft.com/en-us/dotnet/api/system.windows.controls.dockpanel.lastchildfill
The guard MEASURES the widest value with WPF's FormattedText instead of asserting a
magic number, so a font change cannot silently make the field too narrow:
https://learn.microsoft.com/en-us/dotnet/api/system.windows.media.formattedtext

TASK 62 - the border field names its colour.
SceneElement.BorderColorName carries the palette's name for the current colour
("Crimson") and is raised when the colour changes; it is EMPTY for a custom hex the
creator typed, because "no name" is the honest answer. BorderColorPalette.NameOf
changed to match (it used to fall back to the hex itself; the TASK 60 test assertion
was updated with it). The hex field keeps a fixed width (60) so the name sits right
next to the hex instead of drifting to the row's far edge - the same trap as TASK 61.

Guards: ytLive.Tests/GeometryFieldWidthTests.cs, ytLive.Tests/BorderColorNameTests.cs
Full suite: 435/435 passed, 0 warnings.
2026-10-21 22:19:13 -07:00

66 lines
3.2 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System;
using System.Globalization;
using System.Linq;
using System.Windows;
using System.Windows.Media;
using System.Xml.Linq;
using Xunit;
namespace ytLive.Tests;
/// <summary>TASK 61 — the creator (2026-10-21): *"the Y and H boxes under webcam
/// properties should be the same width as the X and W boxes and those widths should be
/// fixed to accommodate the max number of possible digits providing the geometry
/// values."*
///
/// <para>One test: the four geometry fields carry the SAME explicit width (the Y/H
/// fields used to stretch to fill the row, because they were the last child of a
/// DockPanel, while X/W sized themselves to their content), and that width really fits
/// the widest value the panel can show — the largest geometry value (1920 master
/// pixels) with a sign, measured in the app's own font at the field's size.</para></summary>
public class GeometryFieldWidthTests
{
/// <summary>The widest value a geometry field can show: the master frame is
/// 1920×1080, so four digits — plus a sign the creator may be typing.</summary>
private const string WidestValue = "-1920";
[Fact]
public void The_webcam_geometry_fields_share_one_fixed_width_that_fits_the_largest_value()
{
var doc = XDocument.Load(SourceAssert.RepoPath("Controls", "LeftPanel.xaml"));
var geometry = doc.Descendants()
.Where(e => e.Name.LocalName == "TextBlock" && (string?)e.Attribute("Text") == "Geometry")
.Single(e => ((string?)e.Parent?.Attribute("Visibility") ?? "").Contains("IsWebcamSelected"));
var rows = geometry.Parent!.Elements().Where(e => e.Name.LocalName == "DockPanel").ToList();
Assert.Equal(2, rows.Count);
var fields = rows.SelectMany(r => r.Elements().Where(e => e.Name.LocalName == "TextBox")).ToList();
Assert.Equal(4, fields.Count);
// Every field carries the SAME explicit width — a field without one sizes
// itself to its content, and the last one in the row stretches to fill it.
var widths = fields.Select(f => (string?)f.Attribute("Width")).ToList();
Assert.All(widths, w => Assert.False(string.IsNullOrWhiteSpace(w),
"a geometry field has no fixed width — it sizes itself to its content"));
Assert.Single(widths.Distinct());
// And that width fits the widest value the panel can show, in the app's font
// at the field's size, plus the field's own padding and border.
var width = double.Parse(widths[0]!, CultureInfo.InvariantCulture);
var needed = MeasureWidestValue() + 8 /* YtTextBoxCompact padding */ + 2 /* border */;
Assert.True(width >= needed,
$"the geometry fields are {width:0}px wide; {needed:0.#}px are needed for '{WidestValue}'");
}
/// <summary>The width of the widest possible value, in the app's font at 11px.</summary>
private static double MeasureWidestValue()
{
var typeface = new Typeface(SystemFonts.MessageFontFamily,
FontStyles.Normal, FontWeights.Normal, FontStretches.Normal);
return new FormattedText(WidestValue, CultureInfo.CurrentCulture,
FlowDirection.LeftToRight, typeface, 11, Brushes.Black, pixelsPerDip: 1.0).Width;
}
}