Use category-filtered font and selected-item dropdowns, separate horizontal and vertical alignment, and reuse the border-color palette templates for text color. Persist vertical alignment additively. Follow the established static text-source pattern: https://obsproject.com/kb/text-sources
154 lines
7.6 KiB
C#
154 lines
7.6 KiB
C#
using System;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Windows;
|
|
using System.Windows.Controls;
|
|
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")!;
|
|
|
|
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.Equal(10, ((FrameworkElement)fontType.Parent).Margin.Left);
|
|
Assert.Equal(10, ((FrameworkElement)color.Parent).Margin.Left);
|
|
Assert.Equal(10, ((FrameworkElement)horizontal.Parent).Margin.Left);
|
|
Assert.Equal(10, ((FrameworkElement)vertical.Parent).Margin.Left);
|
|
|
|
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;
|
|
}
|
|
}
|