Skip to content

Add FontPicker family plus tests, docs, perf, and reliability fixes - #189

Merged
davidkallesen merged 42 commits into
mainfrom
feature/font-selector
Apr 27, 2026
Merged

davidkallesen merged 42 commits into
mainfrom
feature/font-selector

Conversation

@davidkallesen

Copy link
Copy Markdown
Contributor

Summary

  • Introduce a four-tier FontPicker control family
  • Add ToggleButton theming and ApplicationMonitor context menu
  • Reduce hot-path allocations across panels, dispatcher, and helpers
  • Fix TerminalViewer dispose deadlock and CultureManager event leaks
  • Add CHANGELOG, DocFX scaffold, MVVM migration guide, and package READMEs
  • Expand test suites across core / controls / forms / components / theming / UI

Changes

✨ Features

  • Add FontPicker, AdvancedFontPicker, LabelFontPicker, FontPickerDialogBox
  • Add FontDescription value type and IFontPickerStorage abstraction
  • Add ColorEditorMode DP to swap inline dropdown vs nested color dialog
  • Add BrushToColorNameValueConverter for two-way brush <-> color-name binding
  • Add ToggleButton styles (base + chromeless + Bootstrap variants) + sample
  • Add font-picker translation keys for en / da / de
  • Add ApplicationMonitorView context menu with Copy / CopySelected / CopyAll

🐛 Fixes

  • TerminalViewer: drop dispose-time UI-thread block (1s freeze on close)
  • Messenger: unregister handlers on Unloaded for ZoomBox + monitor view
  • CultureManager: UiCultureChanged is now a weak event (fixes 19 leaks)
  • SVG TextShape: trace parse errors instead of swallowing them
  • ObservableDictionary.CopyTo: implement with proper argument validation
  • Throw NotSupportedException (WPF idiom) for one-way ConvertBack overrides

⚡ Performance

  • VirtualizingStaggeredPanel: reuse scratch HashSet, drop LINQ Max
  • SolidColorBrushHelper: O(1) name->brush lookup instead of LINQ scan
  • DebounceDispatcher: reuse DispatcherTimer + drop per-call closures
  • BitmapImageFactory: load + freeze absolute URIs synchronously
  • GridEx: cache GridLengthConverter
  • ClipBorder: cache combined border-ring Geometry across renders
  • LabelTextInfo / KeepAliveTimer: smaller dispose & timer paths

📦 Dependencies

  • Bump Atc 3.0.18 -> 3.0.67 and Atc.XUnit accordingly
  • Bump analyzer pack (Atc / Meziantou / Sonar / SourceLink)
  • Bump Microsoft.Extensions.* and Microsoft.Windows.CsWin32
  • Bump Microsoft.NET.Test.Sdk and Microsoft.Testing.Extensions.TrxReport

📝 Documentation

  • Add CHANGELOG.md (Keep a Changelog) under [Unreleased]
  • Add CONTRIBUTING.md, CODE_OF_CONDUCT.md, SECURITY.md
  • Add per-package README files for every Atc.Wpf.* project
  • Add Components / Forms category readmes plus sample-app guide
  • Add MVVM migration guide and Mermaid package dependency graph
  • Add DocFX scaffold (docfx.json, root + docs toc, index.md)
  • Add NumericBox and ThicknessBox per-control readmes
  • Refresh CLAUDE.md test counts and Microsoft Testing Platform commands
  • Document BrushToColorNameValueConverter in ValueConverters/@Readme.md

🧪 Tests

  • Add Atc.Wpf.UiTests pilot (FlaUI) with NiceWindow snapshot test
  • Add Atc.Wpf.FontIcons.Tests project
  • Add Atc.Wpf.Benchmarks pilot (BenchmarkDotNet) under /benchmark/
  • Expand core value-converter coverage (brush / color / math / thickness)
  • Expand JSON-tree, observable collection, and extension-method coverage
  • Add Forms FontPicker storage / settings / extractor tests
  • Add Components Flyout / DualListSelector / Terminal event-args tests
  • Add Theming functional value-converter tests
  • Add Controls value-converter and event-args tests

🔧 Configuration

  • Refresh .editorconfig to ATC v1.0.1 with inlined rule descriptions
  • Add per-project .editorconfig files (Components / Forms / Network / etc.)
  • Update CI workflows for new project layout
  • Gitignore _site/, docs/api/, *.metadata.json, and Snapshots/

🔥 Removal

  • Drop unused XUnitTestTypes fixture duplicates from Controls.Tests
  • Remove unused xmlns and BOM from Card.xaml
  • Drop empty SourceGenerators directory note from CLAUDE.md

Notes

  • Font-picker consumers default to inline color dropdown to avoid nested
    dialogs; opt back into the dialog with ColorEditorMode="ColorPicker".
  • Standalone AdvancedFontPicker keeps the dialog-based color picker.
  • Release build of Atc.Wpf.Theming is currently failing with a
    pre-existing WPF MarkupCompile / XAMLColorSchemeGenerator race
    (Light.* baml files); reproduces on this branch without the latest
    font-selector commit and likely needs a separate fix.

Adds: FontPicker, FontFamily, FontSize, FontWeight, FontStyle, FontStretch,
Preview, Foreground, Background, Bold, Italic, Underline, Strikethrough,
Locked, ContrastWarning. Used by the upcoming FontPicker controls.
… variants) and sample

Mirrors the Button.xaml style hierarchy for ToggleButton:
- AtcApps.Styles.ToggleButton (+ .Small / .Large) with an IsChecked trigger
  that swaps Background / BorderBrush to the existing Pressed brushes.
- Chromeless variants with a subtle background fill on checked state.
- 7 Bootstrap colours (Default / Primary / Secondary / Success / Danger /
  Warning / Info), each in solid + outline flavours and 3 sizes. Outline
  variants additionally swap Foreground to white when checked for legibility.

Registers the implicit type style in Controls.xaml so any unstyled
ToggleButton in the codebase picks it up automatically. Adds the
"Theming > Input - Button > ToggleButton" sample page (replacing the
disabled placeholder that was already in the tree).
…tPickerDialogBox

A four-tier font selection stack inspired by the existing ColorPicker
trinity, with feature parity (and several places ahead of) Word /
Google Docs / Figma / VS / Rider:

- FontPicker (compact): "Aa" sample rendered in selected font + family
  name + size in the host UI font + edit button that opens the dialog.
- FontPickerDialogBox: NiceDialogBox wrapper around AdvancedFontPicker
  with OK / Cancel and full TwoWay round-trip of the selection.
- AdvancedFontPicker: full editor with responsive star-column layout.
  Family list with type-ahead search + recently used + virtualised all-
  fonts list; Weight / Style / Stretch lists derived dynamically from
  family.FamilyTypefaces (only valid combinations) with snap-to-closest
  when switching families; Size as IntegerBox + preset list with custom
  sizes auto-inserted; Foreground / Background LabelColorPickers with
  inline swatch; Bold / Italic / Underline / Strikethrough quick toggles
  bound bidirectionally; editable preview text + multi-sample preview
  area (uppercase / lowercase / digits / user text) with theme-aware
  default colours and a WCAG contrast-warning glyph.
- LabelFontPicker: form-tier wrapper mirroring LabelColorPicker.

Granular Show* / IsEnabled* DPs per section, plus 🔒 indicator on
disabled GroupBoxes. Full AutomationProperties.Name + ToolTips, Tab /
arrow / type-ahead navigation. FontDescription value type bundles all
appearance properties (Family, Size, Weight, Style, Stretch, Foreground,
Background, TextDecorations) with ApplyTo / FromControl helpers.

Recents persisted via the new IFontPickerStorage abstraction (default
in-memory, capped to 8); apps wanting cross-restart persistence assign
their own implementation to FontPickerStorage.Current.
…ample pages

- Inputs > FontPicker: compact picker with interactive demo TextBlock
  that mirrors the picker's full appearance (family, size, weight,
  style, stretch, foreground, background, text decorations) plus
  show / enable flag toggles in the side panel.
- Font Editing > AdvancedFontPicker: standalone editor with the same
  side-panel toggles.
- Label Controls > Pickers > LabelFontPicker: forms-tier sample with an
  interactive demo TextBlock plus four labelled variants.

Tree entries added under their respective sample tree views.
…ommands

- Add EnableContextMenu DP plus Copy/CopySelected/CopyAll [RelayCommand] handlers with CanExecute predicates that hide redundant items
- Switch ListView to SelectionMode=Extended and bridge multi-selection into the VM via a SelectionChanged shim
- Add CopyAllToClipboard / CopySelectedToClipboard resource strings (en/da/de)
- Make the sample page stretch the list to fill all available height
…roject configs

- Bump .editorconfig headers from v1.0.0 to v1.0.1 and inline analyzer-rule descriptions in place of doc URLs
- Add per-project .editorconfig files for Components, Forms, Network, UndoRedo, and the Sample app
- Add "Segoe" to the solution user-dictionary
- Atc 3.0.18 -> 3.0.67, Atc.XUnit 3.0.18 -> 3.0.67 across all projects
- Atc.Analyzer 0.1.22 -> 0.1.23, Meziantou.Analyzer 3.0.25 -> 3.0.54, SonarAnalyzer.CSharp 10.21.0 -> 10.24.0, Microsoft.SourceLink.GitHub 10.0.201 -> 10.0.203
- Microsoft.Extensions.* 10.0.5 -> 10.0.7, Microsoft.Windows.CsWin32 0.3.269 -> 0.3.275
- Microsoft.NET.Test.Sdk 18.3.0 -> 18.4.0, Microsoft.Testing.Extensions.TrxReport 2.1.0 -> 2.2.1
- Drop redundant Atc.Test Update from Atc.Wpf.Tests.csproj (centralized to test/Directory.Build.props)
…vent

- Custom add/remove accessors back UiCultureChanged with a List<WeakSubscription>
- Hold delegate Target weakly + Method strongly; detect compiler-generated
  closures via [CompilerGenerated] and keep them strongly so lambda
  subscribers do not die immediately
- Fixes a systemic leak across 19 controls that subscribed without
  unsubscribing (BusyOverlay, NumericBox, ToggleSwitch, label pickers,
  selectors, BasicApplicationSettingsDialogBoxViewModel, etc.)
- Add CultureManagerTests verifying GC-collectability of subscribers
- Replace queueProcessingTask?.Wait(...) with a continuation-based dispose
  so the UI thread no longer blocks on a task that itself uses
  Dispatcher.InvokeAsync (1-second freeze on close gone)
- Unregister Messenger handlers and complete the channel writer in Dispose
- Branch TerminalClearEventArgsHandle on Dispatcher.CheckAccess() and
  fall back to InvokeAsync to avoid sync Invoke from arbitrary threads
- Move ZoomBox and ApplicationMonitorView Messenger registrations to
  Loaded/Unloaded so detached controls stop receiving messages
- TextShape.ParseTSpan: log via Trace.TraceError instead of swallowing
  SVG parse errors silently (mirrors ImageShape pattern)
- VisualPaginator.Source: document the intentional null! return for
  visual-only pagination
- RenderFlagIndicatorTypeToVisibilityValueConverter.ConvertBack and
  ZoomMiniMapClampMultiValueConverter.ConvertBack: throw NotSupportedException
  with a clear message instead of NotImplementedException (WPF idiom)
- ObservableDictionary<TKey, TValue>.CopyTo: implement with proper argument
  validation instead of throwing NotImplementedException
- VirtualizingStaggeredPanel: reuse a scratch HashSet across measure passes
  and replace columnHeights.Max() with a manual loop
- SolidColorBrushHelper: build a parallel name->brush dictionary so
  GetBrushFromString does an O(1) lookup instead of a per-binding LINQ scan
- GridEx.StringLengthsToGridLengths: cache the GridLengthConverter in a
  static field instead of constructing one per parse
- BitmapImageFactory.Create: load absolute URIs synchronously and Freeze
  the resulting bitmap so it is thread-safe and lower-overhead
- DebounceDispatcher.Debounce/Throttle: reuse the DispatcherTimer when
  priority + dispatcher match and store action+param in fields, removing
  per-call closure and timer allocations
…ands

- Update test-file counts to current values (89 / 33 / 25 / 20 / 18 / 12 / 13)
- Add the Atc.Wpf.Components.Tests row that was missing
- Note the FontIcons + SourceGenerators test gaps
- Replace legacy `dotnet test <dir>` snippets with `dotnet run --project ...`
  which is the actual Microsoft Testing Platform invocation
  - VirtualizingStaggeredPanel: replace columnHeights.Max() LINQ with a manual loop
  - KeepAliveTimer: remove redundant lock (Nudge and Tick both run on the UI thread)
  - LabelTextInfo: cache the copy ContextMenu instead of rebuilding it on every flip
  - Introduce Keep-a-Changelog formatted CHANGELOG.md
  - Document weak-event culture manager, TerminalViewer dispose fix, SVG/Messenger/converter
  corrections
  - Capture hot-path allocation reductions across panels, helpers, dispatcher, and label menu
  - Add borderRingGeometryCache field invalidated alongside the existing background/border geometry caches in ArrangeOverride
  - Extract GetOrBuildBorderRingGeometry helper used by all three OnRender paths to avoid rebuilding the Geometry.Combine(...) ring
  on brush-only invalidations
  - Freeze the cached ring for safe reuse
  - Add CONTRIBUTING.md with build/test/PR checklist, project structure, and links to ATC umbrella guidelines
  - Add CODE_OF_CONDUCT.md adopting Contributor Covenant 2.1 by reference
  - Add SECURITY.md documenting private vulnerability reporting via the GitHub Security tab and the supported-version policy
  - Note all three files in CHANGELOG under the unreleased Documentation section
  - Delete five fixture files (Account, Address, DriveItem, Person, PrimitiveTypesModel) — byte-identical copies of the same files in
   Atc.Wpf.Forms.Tests with no consumers in Controls.Tests
  - Drop now-unused System.ComponentModel and System.ComponentModel.DataAnnotations global usings
  - Note the cleanup in CHANGELOG under unreleased Documentation
  - Add CornerRadiusBindingValueConverter tests covering per-corner zeroing, IgnoreRadius fallback, invalid-input default, and
  ConvertBack UnsetValue
  - Add CornerRadiusFilterValueConverter tests covering per-side / per-corner switch, Filter property fallback, Binding.DoNothing on
  bad input
  - Add LeftRightCornerRadiusValueConverter tests covering top-left propagation and zero-radius fallback
  - Add ColorToNameValueConverter tests covering single + multi value paths, Colors.Pink fallback, and ConvertBack semantics
  - Add RenderColorIndicatorTypeToVisibilityValueConverter tests covering Visible/Collapsed mapping and NotSupportedException on
  ConvertBack
  - Expand Theming.Tests GlobalUsings for the new namespaces
  - Update CLAUDE.md row description and refresh the unreleased CHANGELOG section
…gs tests

  - Add FlyoutFormResultFactoryTests covering Success / Cancelled / ValidationFailed shapes
  - Add DualListSelectorItemTests for default state and Name-only ToString
  - Add DualListSelectorItemsReorderedEventArgsTests for index pass-through and per-instance independence
  - Add DualListSelectorItemsTransferredEventArgsTests covering both directions and empty-items case
  - Add TerminalReceivedDataEventArgsTests covering Lines exposure, empty input, and ToString
  - Expose Atc.Wpf.Components.Selectors via GlobalUsings
  - Refresh CLAUDE.md row description and note the addition in CHANGELOG
  - Add IntegerToDoubleValueConverterTests pinning the per-arm boxing semantics in Convert and the implicit double-promotion fallback
   in ConvertBack
  - Add NetworkProtocolToStringValueConverterTests covering all 8 protocol → scheme mappings, scheme → protocol round-trip,
  whitespace trimming, blank/null fallbacks, and Binding.DoNothing for unsupported input
  - Add RenderFlagIndicatorTypeToVisibilityValueConverterTests covering Visible/Collapsed mapping, null/wrong-type/wrong-parameter
  guards, and NotSupportedException on ConvertBack
  - Add StepperStepChangedEventArgsTests and StepperStepChangingEventArgsTests (Cancel defaults to false, settable)
  - Add SegmentedSelectionChangedEventArgsTests covering null items and per-instance index pairs
  - Expose System.Windows.Data, Atc.Wpf.Controls.Selectors, and Atc.Wpf.Controls.ValueConverters via GlobalUsings
  - Refresh CLAUDE.md row description and note the addition in CHANGELOG
  - Add InMemoryFontPickerStorageTests covering LRU promote-on-rerecord, blank-input ignore, MaxRecentItems cap, and snapshot
  isolation
  - Add FontPickerStorageTests for default Current type, null-guard on setter, and custom storage replacement
  - Add LabelControlDataTests for required ctor args, optional defaults, mutable round-trip, and ToString
  - Add LabelInputFormPanelSettingsTests for defaults, round-trip, and ToString
  - Refresh CLAUDE.md row description and note the addition in CHANGELOG
… rectangle

  - Add ThicknessBindingValueConverterTests covering per-side zero-out, IgnoreThicknessSide property fallback, and invalid-input
  default
  - Add ThicknessFilterValueConverterTests covering per-side keep-only, Filter property fallback, and Binding.DoNothing on bad input
  - Add MathValueConverterTests covering single-binding value/parameter operands across +/-/×/÷, multi-binding first-two-values
  operands, divide-by-non-positive guard, null/non-numeric fallbacks, and ConvertBack for both shapes
  - Add RectangleCircularValueConverterTests covering half-of-min-dimension, zero-dimension, wrong-length, non-double, and
  NotSupportedException on ConvertBack
  - Add ColorHexToColorValueConverterTests covering AARRGGBB output, hex parsing (with/without # prefix, 7-char form),
  null/invalid-length Binding.DoNothing, and round-trip
  - Refresh CLAUDE.md row count and total-tests note, and note the addition in CHANGELOG
…ue-converter tests

  - Add ColorToSolidColorValueConverterTests covering alpha-to-255 normalisation, opaque pass-through, DeepPink null fallback,
  wrong-type guard, and NotSupportedException on ConvertBack
  - Add BackgroundToForegroundValueConverterTests covering ideal-text-colour for dark vs light, frozen-brush invariant, multi-binding
   explicit-title pass-through and null-title fallback, and per-targetType UnsetValue ConvertBack
  - Add WindowResizeModeMinMaxButtonVisibilityMultiValueConverterTests covering Min/Max/Close ×
  NoResize/CanMinimize/CanResize/CanResizeWithGrip matrix, useNoneWindowStyle / showButton precedence, and null-values /
  wrong-parameter safe fallbacks
  - Add MethodToValueConverterTests covering parameterless reflection invocation, instance state preservation, missing-method /
  wrong-parameter / null-value safe fallbacks, and NotSupportedException on ConvertBack
  - Add ObservableDictionaryToDictionaryOfStringsValueConverterTests covering string-key + int-key supported variants, null → empty,
  unsupported-type guard, and NotSupportedException on ConvertBack
  - Expose Atc.Wpf.Collections via GlobalUsings
  - Refresh CLAUDE.md row count and total-tests note, and note the addition in CHANGELOG
  - Add JsonArrayLengthConverterTests covering [N] for array nodes vs [ N ] padded form for property-holding-array, empty string for
  non-array property and unsupported input, NotSupportedException on ConvertBack
  - Add JsonNodeChildrenConverterTests covering object property children, array item children, empty for value nodes, null for
  unsupported input, NotSupportedException on ConvertBack
  - Add JsonValueDisplayConverterTests covering DisplayValue for string + numeric value nodes, pass-through for non-JsonValueNode
  input, NotSupportedException on ConvertBack
  - Expose Atc.Wpf.Viewers.JsonTree via GlobalUsings
  - Refresh CLAUDE.md row description and total-tests note, and note the addition in CHANGELOG
  - Add CornerRadiusExtensionsTests covering IsValid matrix across negative/NaN/±∞ flags, IsZero, and IsUniform
  - Add ThicknessExtensionsTests covering the same IsValid matrix plus CollapseThickness width/height sum, IsZero, and IsUniform
  - Add RectExtensionsTests covering Deflate shrink + clamp-to-zero when thickness exceeds size, and Inflate expansion
  - Add ColorExtensionsTests covering Lerp at 0/0.5/1, GetHue for pure red/green/blue, and GetBrightness for black/white
  - Add ObservableDictionaryTests covering Add / ContainsKey / Remove / TryGetValue / indexer / Keys / Values / duplicate-key throw
  plus the new CopyTo guards (null array, negative arrayIndex, insufficient destination size)
  - Refresh CLAUDE.md row description and total-tests note, and note the addition in CHANGELOG
…n tests

  - Add GradientStopCollectionExtensionsTests covering GetColorAtOffset clamp below 0 and above 1, boundary first/last stops,
  byte-truncation midpoint (127, not 128), interpolation within a three-stop segment, and unsorted-stops sort behaviour
  - Add ObservableKeyValuePairTests covering INotifyPropertyChanged for Key and Value, multi-event capture, and direct
  OnPropertyChanged invocation
  - Add ObservableDictionaryExtensionsTests covering all three ToDictionaryOfStrings overloads (string pass-through, int via
  invariant ToString, Guid via default format) plus null-input guards on each
  - Refresh CLAUDE.md row count and total-tests note, and note the addition in CHANGELOG
…nsion tests

  - Add ObservableCollectionExTests covering AddRange single-event semantics, Refresh single Reset, suppress-toggle no-op vs Reset on
   flush, individual Add still raises one event per call, and null-input guard
  - Add BrushExtensionsTests covering IsOpaqueSolidColorBrush matrix on alpha/non-solid types and IsEqualTo across same-reference,
  matching/different solid colour and opacity, different brush types, matching linear gradient, different stop count, different
  radial radius, and null-guard
  - Add DrawingGroupExtensionsTests covering ApplyTransform direct assignment, append to existing TransformGroup,
  wrap-existing-non-group, and null-drawing guard
  - Expose System.Collections.Specialized and Atc.Wpf.Extensions via GlobalUsings
  - Refresh CLAUDE.md row count and total-tests note, and note the addition in CHANGELOG
  - Add Atc.Wpf.UiTests targeting net10.0-windows with FlaUI.Core 5.0.0 + FlaUI.UIA3 + Xunit.StaFact
  - Add SampleAppPath.Resolve() that walks up to the .slnx and probes the sample bin folder for Atc.Wpf.Sample.exe
  - Add SampleAppSmokeTests.Sample_app_launches_and_shows_main_window — launches the sample, asserts a non-empty main window title,
  captures a screenshot to bin/<Config>/net10.0-windows/Snapshots/, then closes
  - Skip by default with [Trait("Category","UI")] so headless CI stays green; opt in by removing the Skip locally
  - Add Readme documenting the run pattern and rationale (FlaUI vs Verify.Wpf vs PercyIO)
  - Register the new project in Atc.Wpf.slnx
  - Add docfx.json that pulls API metadata from all 8 source projects, drops references under docs/api/, and builds existing docs/
  markdown plus a new index.md landing page
  - Add root toc.yml (Home / Documentation / API Reference / GitHub) and docs/toc.yml ordering the left nav by category
  - Add index.md landing page with a curated section index and local-preview instructions
  - Gitignore _site/, docs/api/, and *.metadata.json
  - Update CLAUDE.md SourceGenerators caveat to point at the Atc.XamlToolkit NuGet packages instead of the empty directory
  - Note the docs scaffold, the SourceGenerators directory removal, and the Atc.Wpf.UiTests pilot in CHANGELOG
  - Add docs/Mvvm/Migration.md covering hand-rolled INotifyPropertyChanged / RelayCommand / DependencyProperty / AttachedProperty →
  source-generator attribute migration, including a TL;DR table, side-by-side examples, a cookbook, and a pre-flight checklist
  - Cross-link the new guide from docs/Mvvm/@Readme.md
  - Nest MVVM as Overview + Migration guide in docs/toc.yml
  - Add a Mermaid package dependency graph to README.md showing the four-tier core (blue → green) and the side packages (orange)
  plugging into it
  - Add Atc.Wpf.Benchmarks under new /benchmark/ solution folder, kept out of
    test/ so dotnet test never picks it up
  - Override BDN toolchain to net10.0-windows in BenchmarkConfig to fix NU1201
    against the WPF-targeted Atc.Wpf assembly
  - Add SolidColorBrushHelperBenchmarks ([MemoryDiagnoser], 4 color params) to
    pin the O(1) reverse lookup in GetBrushFromString
  - Document run commands, --job toolchain gotcha, and convention to add a
    benchmark per hot-path fix
  - Update CHANGELOG with rationale and verified perf (~10–12 ns/op, 0 alloc)
  - Add NiceWindowSnapshotTests asserting ClassName=="NiceWindow" (proves
    themed chrome is active, not a Window fallback) and capturing full window
    plus a 40px title-bar strip for low-noise theming diffs
  - Maximize via Window pattern + SetForeground before Capture() so the
    element-based screenshot isn't polluted by overlapping windows
  - Wrap Close()/WaitWhileMainHandleIsMissing in try/catch in both tests:
    the wait races with Close() on fast machines and FlaUI throws a wrapped
    System.Exception; using-on-Application still disposes
  - Document the Capture() Z-order trap, Bitmap.Clone overload pitfall, and
    new test pattern in Readme; update CHANGELOG with both tests and rationale
  - Add FontColorEditorMode enum and ColorEditorMode DP on AdvancedFontPicker,
    FontPickerDialogBox, FontPicker, and LabelFontPicker; the consumer-tier
    controls default to WellKnownColorSelector to avoid opening a nested
    color-picker dialog inside the font dialog (override with ColorPicker).
  - Add BrushToColorNameValueConverter for two-way SolidColorBrush <-> color
    key binding, with unit tests covering known/unknown brushes and DoNothing
    fallbacks; document it in ValueConverters/@Readme.md.
  - Wire a ColorEditorMode chooser into the AdvancedFontPicker sample demo
    and add a CHANGELOG entry under [Unreleased].
@davidkallesen
davidkallesen merged commit b48d3b6 into main Apr 27, 2026
2 checks passed
@davidkallesen
davidkallesen deleted the feature/font-selector branch April 27, 2026 10:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant