Repository navigation
Add FontPicker family plus tests, docs, perf, and reliability fixes - #189
Merged
Merged
Conversation
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
…ationMonitorView context menu
- 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].
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Changes
✨ Features
🐛 Fixes
⚡ Performance
📦 Dependencies
📝 Documentation
🧪 Tests
🔧 Configuration
🔥 Removal
Notes
dialogs; opt back into the dialog with ColorEditorMode="ColorPicker".
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.