Put size and color on one row, place emphasis labels before their toggles, and split the remaining font families into handwriting, symbols, and international groups while omitting legacy dingbat fonts. Text-layer properties follow the existing hierarchical layout and palette conventions.
170 lines
8.5 KiB
C#
170 lines
8.5 KiB
C#
using System;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Windows;
|
|
using System.Windows.Controls;
|
|
using System.Windows.Controls.Primitives;
|
|
using Microsoft.Data.Sqlite;
|
|
using Xunit;
|
|
using ytLive.Controls;
|
|
using ytLive.Models;
|
|
using ytLive.ViewModels;
|
|
|
|
namespace ytLive.Tests;
|
|
|
|
[Collection("RealApp")]
|
|
public sealed class TextLayerDropdownTests
|
|
{
|
|
private readonly RealAppHost _app;
|
|
|
|
public TextLayerDropdownTests(RealAppHost app) => _app = app;
|
|
|
|
[Fact]
|
|
public void Text_Controls_Show_Defaults_Update_And_Restore_Selected_Values()
|
|
{
|
|
_app.Run(Run);
|
|
}
|
|
|
|
private static void Run()
|
|
{
|
|
var dbPath = Path.Combine(Path.GetTempPath(), $"ytLlive-text-controls-{Guid.NewGuid():N}.db");
|
|
MainViewModel.LayoutPathOverride = dbPath;
|
|
MainWindow? window = null;
|
|
try
|
|
{
|
|
window = new MainWindow();
|
|
var vm = (MainViewModel)window.DataContext;
|
|
vm.EditingActive = true;
|
|
vm.StagedScene = vm.Scenes.Single(scene => SceneCatalog.Is(scene.Name, SceneCatalog.Live));
|
|
vm.AddSourceCommand.Execute(SourceType.TextOverlay);
|
|
var source = vm.StagedScene!.Elements.OfType<Source>()
|
|
.Single(item => item.Type == SourceType.TextOverlay);
|
|
vm.SelectedElement = source;
|
|
|
|
window.Show();
|
|
window.UpdateLayout();
|
|
|
|
var panel = (LeftPanel)window.FindName("LeftPanel")!;
|
|
var fontType = (ComboBox)panel.FindName("TextLayerFontTypePicker")!;
|
|
var font = (ComboBox)panel.FindName("TextLayerFontPicker")!;
|
|
var size = (ComboBox)panel.FindName("TextLayerSizePicker")!;
|
|
var colorField = (TextBox)panel.FindName("TextLayerColorEditor")!;
|
|
var color = (ComboBox)panel.FindName("TextLayerColorPicker")!;
|
|
var horizontal = (ComboBox)panel.FindName("TextLayerHorizontalAlignmentPicker")!;
|
|
var vertical = (ComboBox)panel.FindName("TextLayerVerticalAlignmentPicker")!;
|
|
var boldToggle = (ToggleButton)panel.FindName("TextBoldToggle")!;
|
|
|
|
Assert.Equal("Sans Serif", fontType.SelectedItem);
|
|
Assert.Equal("Sans Serif", fontType.Text);
|
|
Assert.Equal("Segoe UI", font.SelectedItem);
|
|
Assert.Equal("Segoe UI", font.Text);
|
|
Assert.Equal(48d, size.SelectedItem);
|
|
Assert.Equal("48", size.Text);
|
|
Assert.Equal("#FFFFFF", colorField.Text);
|
|
Assert.Equal(source.TextColorEntry, color.SelectedItem);
|
|
Assert.Equal(TextLayerAlignment.Left, horizontal.SelectedItem);
|
|
Assert.Equal("Left", horizontal.Text);
|
|
Assert.Equal(TextLayerVerticalAlignment.Top, vertical.SelectedItem);
|
|
Assert.Equal("Top", vertical.Text);
|
|
|
|
Assert.Same(Application.Current.Resources["YtComboBox"], color.Style);
|
|
Assert.Same(panel.Resources["BorderColorTemplates"], color.ItemTemplateSelector);
|
|
Assert.Same(size.Parent, colorField.Parent);
|
|
Assert.Same(size.Parent, color.Parent);
|
|
Assert.Equal(10, ((FrameworkElement)panel.FindName("TextTypographyOptions")!).Margin.Left);
|
|
Assert.Equal(10, ((FrameworkElement)panel.FindName("TextEmphasisOptions")!).Margin.Left);
|
|
Assert.Equal(10, ((FrameworkElement)horizontal.Parent).Margin.Left);
|
|
Assert.Equal(10, ((FrameworkElement)vertical.Parent).Margin.Left);
|
|
var boldRow = (DockPanel)boldToggle.Parent;
|
|
Assert.True(boldRow.Children.IndexOf(boldRow.Children[0]) < boldRow.Children.IndexOf(boldToggle));
|
|
Assert.Equal("Bold", ((TextBlock)boldRow.Children[0]).Text);
|
|
|
|
fontType.SelectedItem = "Symbols";
|
|
window.UpdateLayout();
|
|
Assert.DoesNotContain(vm.TextFontFamilies, item => item is "Webdings" or "Wingdings" or "Wingdings 2" or "Wingdings 3");
|
|
Assert.Equal("Segoe UI", source.TextFontFamily);
|
|
|
|
fontType.SelectedItem = "Sans Serif";
|
|
window.UpdateLayout();
|
|
Assert.Equal("Segoe UI", font.SelectedItem);
|
|
|
|
fontType.SelectedItem = "Serif";
|
|
window.UpdateLayout();
|
|
Assert.Equal("Serif", vm.SelectedTextFontType);
|
|
Assert.Equal("Segoe UI", source.TextFontFamily);
|
|
Assert.NotEmpty(font.Items);
|
|
var serifFont = font.Items.Cast<string>().First();
|
|
font.SelectedItem = serifFont;
|
|
size.SelectedItem = 36d;
|
|
color.SelectedItem = source.TextColorOptions.Single(item => item.Hex == "#FF0000");
|
|
horizontal.SelectedItem = TextLayerAlignment.Center;
|
|
vertical.SelectedItem = TextLayerVerticalAlignment.Bottom;
|
|
window.UpdateLayout();
|
|
|
|
Assert.Equal(serifFont, source.TextFontFamily);
|
|
Assert.Equal(36, source.TextFontSize);
|
|
Assert.Equal("#FF0000", source.TextColor);
|
|
Assert.Equal(TextLayerAlignment.Center, source.TextAlignment);
|
|
Assert.Equal(TextLayerVerticalAlignment.Bottom, source.TextVerticalAlignment);
|
|
var raster = Assert.IsType<ytLive.Services.VideoFrame>(vm.ResolveOutputFrame(source));
|
|
Assert.True(FirstInkRow(raster) > 50,
|
|
"bottom alignment did not place the text lower inside its box");
|
|
Assert.Equal("Serif", fontType.SelectedItem);
|
|
Assert.Equal(serifFont, font.SelectedItem);
|
|
Assert.Equal(serifFont, font.Text);
|
|
Assert.Equal(36d, size.SelectedItem);
|
|
Assert.Equal("36", size.Text);
|
|
Assert.Equal("#FF0000", colorField.Text);
|
|
Assert.Equal(source.TextColorEntry, color.SelectedItem);
|
|
Assert.Equal(TextLayerAlignment.Center, horizontal.SelectedItem);
|
|
Assert.Equal("Center", horizontal.Text);
|
|
Assert.Equal(TextLayerVerticalAlignment.Bottom, vertical.SelectedItem);
|
|
Assert.Equal("Bottom", vertical.Text);
|
|
|
|
vm.SaveLayoutNow();
|
|
window.Close();
|
|
window = null;
|
|
SqliteConnection.ClearAllPools();
|
|
|
|
window = new MainWindow();
|
|
var reloadedVm = (MainViewModel)window.DataContext;
|
|
reloadedVm.EditingActive = true;
|
|
reloadedVm.StagedScene = reloadedVm.Scenes.Single(scene => SceneCatalog.Is(scene.Name, SceneCatalog.Live));
|
|
var reloaded = reloadedVm.StagedScene.Elements.OfType<Source>()
|
|
.Single(item => item.Type == SourceType.TextOverlay);
|
|
reloadedVm.SelectedElement = reloaded;
|
|
window.Show();
|
|
window.UpdateLayout();
|
|
|
|
var reloadedPanel = (LeftPanel)window.FindName("LeftPanel")!;
|
|
Assert.Equal(reloadedVm.SelectedTextFontType, ((ComboBox)reloadedPanel.FindName("TextLayerFontTypePicker")!).SelectedItem);
|
|
Assert.Equal(reloaded.TextFontFamily, ((ComboBox)reloadedPanel.FindName("TextLayerFontPicker")!).SelectedItem);
|
|
Assert.Equal(reloaded.TextFontFamily, ((ComboBox)reloadedPanel.FindName("TextLayerFontPicker")!).Text);
|
|
Assert.Equal(reloaded.TextFontSize, ((ComboBox)reloadedPanel.FindName("TextLayerSizePicker")!).SelectedItem);
|
|
Assert.Equal(reloaded.TextFontSize.ToString(), ((ComboBox)reloadedPanel.FindName("TextLayerSizePicker")!).Text);
|
|
Assert.Equal(reloaded.TextColor, ((TextBox)reloadedPanel.FindName("TextLayerColorEditor")!).Text);
|
|
Assert.Equal(reloaded.TextColorEntry, ((ComboBox)reloadedPanel.FindName("TextLayerColorPicker")!).SelectedItem);
|
|
Assert.Equal(reloaded.TextAlignment, ((ComboBox)reloadedPanel.FindName("TextLayerHorizontalAlignmentPicker")!).SelectedItem);
|
|
Assert.Equal(reloaded.TextAlignment.ToString(), ((ComboBox)reloadedPanel.FindName("TextLayerHorizontalAlignmentPicker")!).Text);
|
|
Assert.Equal(reloaded.TextVerticalAlignment, ((ComboBox)reloadedPanel.FindName("TextLayerVerticalAlignmentPicker")!).SelectedItem);
|
|
Assert.Equal(reloaded.TextVerticalAlignment.ToString(), ((ComboBox)reloadedPanel.FindName("TextLayerVerticalAlignmentPicker")!).Text);
|
|
}
|
|
finally
|
|
{
|
|
window?.Close();
|
|
MainViewModel.LayoutPathOverride = null;
|
|
SqliteConnection.ClearAllPools();
|
|
try { File.Delete(dbPath); } catch { /* best-effort cleanup */ }
|
|
}
|
|
}
|
|
|
|
private static int FirstInkRow(ytLive.Services.VideoFrame frame)
|
|
{
|
|
for (var y = 0; y < frame.Height; y++)
|
|
for (var x = 0; x < frame.Width; x++)
|
|
if (frame.BgraPixels[(y * frame.Width + x) * 4 + 3] > 0)
|
|
return y;
|
|
return frame.Height;
|
|
}
|
|
}
|