Files
LlamaCasty/Controls/index.md
T

7.2 KiB
Raw Blame History

Controls — index

The phase-2 carved pieces of what used to be one monolithic MainWindow.xaml (1,681 lines → a 123-line shell). Each is a UserControl in the ytLive.Controls namespace, extracted one roll-back commit at a time (refactor-commit-12..18). See schema.md for the memory-map conventions.

File Purpose
BottomBar.xaml(.cs) Footer (Row 3): stream stats (bitrate/fps/dropped/duration/health), resolution dropdown (gear menu moved up to TopBar 2026-09-22)
HealthBanner.xaml(.cs) Row 1 status banner + the 7 value→visibility converters live in the app theme, not here
TopBar.xaml(.cs) Row 0 session surface (2026-09-22 redesign): brand + gear menu (left), one segmented REC
PreviewPane.xaml(.cs) Row 1 Col 1 center: the 1920×1080 OverlayCanvas/SelectionOverlay/BrandFlashLayer/SocialBarElement, text pull-out drawer, and the live-controls row (TRAX / game / mic meters + sliders + speakers + socials). TASK 57: dragging a webcam under the vertical tier routes through MainViewModel.MoveWebcamInVerticalTier (the six-spot snap inside the cropped band) instead of free-floating over the master, and a resize re-snaps the tile onto its spot (TASK 57 Unit 2: the resize routes through MainViewModel.ResizeWebcamInVerticalTier — the Chat camera's two sizes, then the snap)
SceneThumbnailStrip.xaml(.cs) Row 0 scene-picker strip (ItemsControl over Scenes), staged-red / live-green border highlight
LeftPanel.xaml(.cs) Row 1 Col 0 left panel: edit mode → layers+properties; live → YouTube chat. Source add/edit/remove, list drag-to-reorder, snapshot revert-accept. TASK 51: the webcam properties carry the Background section — RemoveBackgroundPill / BlurBackgroundPill (PillToggle, radio-exclusive via WebcamSceneConfig.RemoveBackground/BlurBackground) + BackgroundStrengthSlider (0..1, 5% snaps, shown only while an effect is on). TASK 57: the webcam properties carry a Geometry section (X/Y/W/H) — manual placement of the camera, bound to the live placement (the one the current tier shows), gated on IsWebcamSelected (not SelectedElement.IsWebcam — the TASK 51 test finds that panel by binding text and would match twice); the Shape button's Visibility is bound to CanToggleClipShape, so the circle option is NOT OFFERED in the vertical Chat layout. TASK 58: every drop-down, check box and field in the properties panel carries the theme's style (YtComboBox/YtCheckBox/YtTextBoxCompact) and paints no colour of its own — the guard is ytLive.Tests/PropertiesStyleTests.cs. TASK 59: the webcam's properties are a HIERARCHY — a Shape title owns the mirror switch and the shape choice (Rect
OverlayHost.xaml(.cs) Root-grid overlay dialogs: Settings / Report Bug / Feature Request / About (+ licenses + license-key entry). BackToAbout_Click lives here
SceneThumbnailStrip.xaml.cs Code-behind for the strip above
LeftPanel.xaml.cs Code-behind for the panel above

Window ↔ control contract

The shell (MainWindow.xaml(.cs)) wires up each control and routes the few cross-cutting calls through it:

  • Ctor finds each control by x:Name (TopBar, PreviewPane, LeftPanel) AFTER InitializeComponent, before any method touches it (null-ref guard).
  • _previewPane.IsClickInsidePreview/Drawer + _leftPanel.IsClickInside → deselection guard in Window_PreviewMouseLeftButtonDown.
  • _previewPane.UpdateSelectionOverlay(bool) + _leftPanel.OnSelectionChanged(vm) → selection/edit-mode routing from the VM's SelectedElement change.
  • _topBar.RefreshAvatar() on IsConnected/AccountAvatarUrl change.
  • Handlers in moved controls cast (DataContext as MainViewModel) — controls inherit the window's DataContext; never pass the VM through a property.

Gotchas learned the hard way

  • A UserControl cannot see Window.Resources (StaticResource resolves by element lookup, so it stops at the control boundary). The 7 converters (BoolToVis, InverseBoolToVis, NotNullToVis, NullToVis, HiddenBoolToVis, EnumToBool, AllTrueToVis) were promoted from MainWindow.Resources into Themes/Controls.xaml (see Themes/index.md).
  • Moved XAML can lose its namespace: a block cut from MainWindow carries no root xmlns, so any models:/Helpers: ref in it breaks the build with MC2000: Value cannot be null (key). Declare xmlns:models / xmlns:Helpers on each control's root (LeftPanel hit this).
  • Name-looked-up host stubs must stay in the window, not a control: WebViewHostPanel (ctor InitWebView2(WebViewHostPanel)) and ToastArea (NotificationService.InArea("ToastArea")) are resolved by name from the window root — so OverlayHost deliberately leaves them as thin window-root children (Commit 18). Since the 2026-09-14 composition-capture redesign only ToastArea remains — WebViewHostPanel is deleted (web sources no longer host a multiline XAML control; InitWebView2() runs from MainWindow_Loaded with no panel argument).
  • When cutting visual wrappers, don't drop the outer Border's background/glow/margin — Commit 15 initially lost the preview's outer border and had to restore it same-commit.

Related: ViewModels/index.md (MainViewModel the controls bind to), Themes/index.md (styles/converters), Helpers/index.md (ViewModelBase, converters), the MainWindow.xaml shell at repo root that hosts these.