Native dialogs migration (spec 011)#75
Merged
Merged
Conversation
Spec covers the remaining Win32 UI surfaces left after 007: - unified startup download dialog (ROMs + Disk II audio) - boot disk picker with per-user MRU - themed dialog primitive (extracted from SettingsWindow) - About / Keymap / Machine Info conversions - drive widget filename label - file-open path dedup - DebugConsole + DiskIIDebugDialog DX conversions Preserves two Win32 escape hatches: IFileOpenDialog in PromptForDiskImage, and the top-level EHM notify MessageBoxW. 65 tasks across 11 phases (P1 ships independently as MVP). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ncation
Foundational primitives for native DX dialog work (spec 011):
- Casso/Ui/Dialog/DialogDefinition.h: pure value types (DialogIcon,
DialogTextRun, DialogButton, DialogDefinition) + custom-body paint/
input hook signatures matching contracts/dialog-primitive.md.
- Casso/Ui/Dialog/DialogLayout.{h,cpp}: pure LayoutDialog free function
taking DialogDefinition + DialogLayoutMetrics with injected text
measurement callbacks. Produces icon rect, per-run body rects with
greedy wrap, hyperlink hit rects, button row (right-aligned), and
optional custom-body rect.
- Casso/Shell/DiskMru.{h,cpp}: pure most-recently-used list helper
with k_capacity = 16, move-to-front dedup, oldest eviction at cap,
Prune via injected exists predicate. No file I/O.
- Casso/Ui/Chrome/DriveLabelTruncation.{h,cpp}: pure basename
truncation with single-character U+2026 ellipsis via injected
measure callback.
- Headless unit tests for all three (DialogLayoutTests, DiskMruTests,
DriveLabelTruncationTests) with deterministic stub measurers.
No behavioral wiring yet -- the DialogPrimitive overlay, GlobalUserPrefs
recentDisks JSON field, and consumer dialogs land in follow-on commits.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Adds top-level recentDisks string array to the unified user prefs JSON, most-recent-first, cap enforced at use sites by DiskMru. - Casso/Config/GlobalUserPrefs.h: new std::vector<std::string> recentDisks member. - Casso/Config/GlobalUserPrefs.cpp: ToJson emits recentDisks after the window block; FromJson reads it, silently dropping non-string and empty entries per data-model.md sec.1; recentDisks added to s_knownTopLevel so unknown-passthrough doesn't double-emit it. - UnitTest/UiTests/GlobalUserPrefsTests.cpp: round-trip test + malformed-entry tolerance test. MRU plumbing into a DiskMru owned by GlobalUserPrefs (T013) and mount- site recording (T021) are intentionally deferred until the dialog primitive lands -- without consumers wired up, in-memory MRU state has no producer. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Route IDM_DISK_INSERT1 / IDM_DISK_INSERT2 through the existing modern PromptForDiskImage (IFileOpenDialog) and delete the legacy GetOpenFileNameW branch from OnDiskCommand. FR-015 keeps IFileOpenDialog as the single supported file-picker surface; legacy ANSI common-dialog path is gone. Ctrl+1 / Ctrl+2 accelerators (FR-014) untouched -- they still emit the same IDM_DISK_INSERT* commands; only the dispatch handler changed. MRU recording and drive-widget label updates that the spec attaches to this flow plug in through PromptForDiskImage's Mount() seam once the dialog primitive and DriveWidget extension land. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Paints the mounted disk's basename below 'DRIVE N' on the faceplate, hidden when no disk is mounted, ellipsis-truncated when the basename is wider than the available faceplate width. - Casso/Ui/Chrome/DriveWidget.cpp: skeuomorphic paint path now renders the basename one line below 'DRIVE N' at labelFontDip - 2 dip, using DriveLabelTruncation::TruncateToWidth backed by DwriteTextRenderer::MeasureString. - The existing DriveWidgetState::mountedImagePath wstring field carries the mount/eject signal -- no new state plumbing required. Unit-tested truncation algorithm already covered by DriveLabelTruncationTests (7 cases including degenerate, multi-dot, no-extension). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Marks the foundational primitives (DialogDefinition, DialogLayout, DiskMru, DriveLabelTruncation, GlobalUserPrefs recentDisks schema, drive widget filename label, disk-insert file-picker dedup) as the shipped 1.4.1267 slice of spec 011. Remaining 43 tasks (US1, US2, US3, US6, US7, plus T006-T009 dialog primitive itself, T013 MRU owner, T038 SettingsPanel stray) marked [!] blocked in tasks.md with rationale: all gated on T006 -- the themed modal-overlay Win32 window extracted from SettingsWindow.cpp's 800-line scaffolding -- which is genuinely a multi-day integration task requiring debug cycles against EmulatorShell's render loop that didn't fit one session. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Add s_kchEllipsis (U+2026) to UnicodeSymbols.h; remove inline L'\u2026' literals from DriveLabelTruncation and its tests. - Convert anonymous-namespace helpers in DialogLayout.cpp into a DialogLayout class with private static helpers + nested LayoutState. Factor 160-line Compute into BeginLayout / PerformBodyWrap / BuildBodyRunRects / BuildHyperlinkHitRects / BuildIconRect / BuildCustomBodyRect / BuildButtonRects / ComputeTotalSize. - DiskMru, DriveLabelTruncation, FindWrapBoundary, WrapBody: convert early-return patterns to single-exit (EHM-style structural flow). - Update DialogLayoutTests to call DialogLayout::Compute. 1614/1614 unit tests passing. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Implement DialogPrimitive and DialogPrimitiveRenderer, the modal dialog primitive requested in spec 011-native-dialogs-completion. DialogPrimitiveRenderer owns a CreateSwapChainForHwnd swap chain (DXGI_ALPHA_MODE_IGNORE, no DComp or blur shaders), RTV, DxUiPainter geometry layer, and DwriteTextRenderer text layer. Paints a gradient title bar, theme-colored background, icon circle for Info/Warning/ Error/App variants, word-wrapped body text runs, hyperlink underlines, optional custom-body callback (progress bars etc.), and Button widgets from the existing Widgets/Button widget. DialogPrimitive owns the Win32 class lifetime (RegisterClass/ UnregisterClass), creates the window as WS_POPUP|WS_SYSMENU (no NC area, client == window), and runs a private GetMessage loop inside Show() that disables the owner window for the duration. Returns the chosen button resultCode or -1 on close gesture. Close() records the result and posts WM_NULL to unblock the loop. Keyboard shortcuts: Enter fires the focused or default button; Escape fires the cancel button or Close(-1); Tab/Shift-Tab cycles focus between buttons; Space fires the focused button. Hyperlinks launch via ShellExecuteW with a CHRN user-facing notification on failure. Also fixes a pre-existing ChromeTheme forward-declaration mismatch in DialogDefinition.h (class -> struct). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…e (US3, T038) Adds EmulatorShell::ShowModalDialog helper that lazy-registers the dialog window class and hands the primitive the renderer device/context/theme. Converts the Help->Keymap, Help->About (with clickable github link + AppPhotoreal icon), Machine Info, and SettingsPanel ROM-download failure dialogs from native MessageBoxW to the themed DialogPrimitive. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…US1) Replace TaskDialogIndirect/MessageBoxW in PromptUser, PromptBootDisk and PromptDiskAudioConsent with the new themed StandaloneDialog helper (transient D3D11 + Skeuomorphic theme since EmulatorShell does not exist yet at bootstrap time). Add s_kchAlmostEqual to UnicodeSymbols.h. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Every successful EmulatorShell::Mount now pushes the image path through DiskMru::FromUtf8 / RecordMount / ToUtf8 and persists the updated MRU list to UserPrefs.json. Best-effort: MRU write failures cannot block a successful mount. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…tion Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Debug Console and Disk II Debug dialog now use immersive dark caption, dark client backgrounds, themed read-only edit, ListView text/bg/header colors via SetWindowTheme(DarkMode_Explorer). Both remain modeless Win32 windows but visually match the rest of the chrome. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
When no disk is configured at startup, prompt the user with a themed dialog listing recent disk images (pruned to those still on disk). Selecting a row mounts that image; Download falls through to the asset bootstrap flow; Cancel/Esc skips and boots without a disk. Extends DialogPrimitive with a custom-body input dispatcher so dialog consumers can implement clickable regions and hover state. Adds the DwriteTextRenderer pointer to DialogPaintContext so custom-body paint callbacks can render text. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The basename used to paint inside the faceplate, right under DRIVE N, where it overlapped the disk slot in the skeuomorphic theme. Moved the label out of the faceplate and into a dedicated strip below m_bodyRect that's shared by both the skeuomorphic and compact paint paths. Drive bar thickness bumped (192 to 212 dp full, 64 to 84 dp compact) to make room for the new strip; LayoutDriveWidgetsInCommandBar now centers on OuterRect so the body + label both fit cleanly. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Anchor drive widgets to the bottom of the command bar so the gap between the basename label and the window edge mirrors s_kLabelStripGapPx (2 dp), instead of vertically centering and leaving uneven margins. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Mount a fake disk on the preview DriveWidgets so the basename label strip renders. Bump preview bar heights (212/84 dp) and anchor widgets via OuterRect with a 2 dp bottom gap, matching the live command bar. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Wire a MountedPathSource callback from SettingsPanel through ThemePage so the preview drive widgets display the actual basenames of the disks currently in drive 1 and drive 2 (or no label if empty). Replaces the hardcoded mock filename. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
DialogLayout::WrapBody previously treated '\n' as a normal character, so multi-paragraph body text (with embedded '\n' or '\n\n') was greedily wrapped into a single paragraph and DWrite then drew the per-run text into a too-small unioned rect, causing severe overlap with the button row (e.g. the ROM download prompt). Now split each run on '\n', forcing a hard line break at every newline and emitting a zero-width marker for empty segments so the unioned bounding rect grows to include blank lines. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Four fixes to the themed download-ROMs dialog: 1. PaintIcon now loads IDI_CASSO_PHOTOREAL / IDI_CASSO from the resource section and renders it via DwriteTextRenderer::DrawIconBitmap instead of falling back to the grey placeholder circle. 2. PaintBody iterates per-line wrapped pieces published by DialogLayout (new wrappedPiecesPx with absolute pixel coords) and draws each substring at its exact rect. This eliminates the spurious 'Would you like to download them' wrap caused by DWrite re-wrapping inside the unioned bounding rect. 3. AssetBootstrap::PromptUser body text rewritten for readability: single intro line plus URL hyperlink, with the question implicit in the Download/Cancel buttons. 4. The missing-ROMs list is now a two-column zebra-striped table rendered via onPaintCustomBody (filename | description) instead of bullet text that wrapped mid-description. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Use silhouette icon (IDI_CASSO) for the missing-ROMs dialog instead of the photoreal disk render so the iconography matches the rest of the chrome. - Bump body font from 11dp to 13dp (line height 18 -> 22) so dialog copy reads as cleanly as button labels at every DPI. - Add linkArgb/linkHoverArgb to ChromeTheme with per-theme values bright enough to be legible on the dropdown background. Hyperlinks now render in linkArgb, brighten to linkHoverArgb on hover/focus, and the focused link gets a 1px focus ring. - Hyperlinks join the Tab focus cycle alongside buttons. Enter or Space activates the focused link; mouse hover switches the cursor to IDC_HAND via WM_SETCURSOR. - Scale the ROM list table row metrics by ctx.dpiScale (the font was scaling but the row height was raw pixels, causing text overlap on high-DPI displays). Reserve the table area using the system DPI at PromptUser call time so the dialog grows to fit. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Focus ring around a wrapped hyperlink now draws one rect per wrapped piece (using DialogLayout's wrappedPiecesPx) instead of one giant bounding rect that covered intervening non-link text. - Missing-ROMs table grows a styled header row (navHoverArgb fill, titleTextArgb labels, Segoe UI Semibold) with 'ROM File' and 'Description' captions above the data rows. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ert on second Show - DwriteTextRenderer::DrawString gains optional DWRITE_FONT_WEIGHT param (default Normal), with weight folded into the text-format cache key. Lets the ROM dialog headers actually render bold instead of Semibold pretending. - DialogDefinition gains iconSizeOverrideDp so individual dialogs can ask for a bigger icon. ROM dialog uses 64dp (2x default). - ROM dialog copy reworded (sentence-case 'ROM file' header, single-line intro that flows into the link), trailing space before the URL so focus ring no longer butts against text. - DialogPrimitive::RegisterClass now sets m_hInstance BEFORE bailing on the class-already-registered path. Second standalone dialog (e.g. PromptBootDisk after a ROM prompt has already registered the class) was hitting CBRA(m_hInstance) on Show. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ented stay checked Removes the [!] [BLOCKED] markings that were declaring premature defeat on tasks that genuinely still need work. Marks as [X] only the tasks I just verified by code citation: T006-T009 (DialogPrimitive + hyperlink + keyboard + ShellExec): file exists, hyperlinks added this session. T012-T013 (recentDisks JSON + DiskMru wiring): GlobalUserPrefs reads/writes recentDisks, RecordMount called from EmulatorShell. T025-T028 (About/Keymap/Machine-Info themed, AppPhotoreal icon): WindowCommandManager routes those commands through ShowModalDialog; DialogPrimitiveRenderer maps AppPhotoreal to IDI_CASSO_PHOTOREAL. T036 (GetOpenFileNameW removed): only IFileOpenDialog remains in WindowCommandManager. T038 (SettingsPanel MessageBoxW): replaced with ShowModalDialog at line 1545. Everything else is back to [ ] until it has actual code or a human walkthrough behind it. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Replace the separate ROM-prompt + Disk II audio-consent dialogs with one themed DX dialog (StartupDownloadDialog) that scans for every missing asset and downloads them all on a worker thread with live per-asset progress. AssetBootstrap::RunStartupDownloader is the new unified entry point. Main.cpp and SettingsPanel.cpp now route their pre-flight through it. Download work runs on a worker thread; UI thread just paints status and routes input. Exit cancels in-flight downloads cleanly (atomic flag checked between WinHTTP chunks). Button policy: ROMs missing -> [Download][Exit] (no Skip, can't boot). Otherwise -> [Download][Skip][Exit]. After Download is clicked, label becomes 'Downloading...' disabled, Skip is hidden, Exit stays active. DialogPrimitive grew SetButtonLabel/Enabled/Visible, Repaint, onTick + onButtonActivated hooks. DownloadHttp + FetchAndDecodeOgg grew optional progress/cancel atomics. Legacy CheckAndFetchRoms / PromptUser / CheckAndFetchDiskAudio / PromptDiskAudioConsent remain in AssetBootstrap.cpp for now; they're no longer called and will be removed in a follow-up commit. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…loader - Collapse 8 per-WAV audio rows into a single `Disk II drive audio'' entry with one progress bar; the worker iterates the catalog internally, skipping files already on disk and tolerating per-file fetch failures. - New StartupAssetKind::BootDisk; first-launch path can append a stock DOS 3.3 System Master entry so the dialog shows ROMs, drive audio, AND a boot disk in one screen. - StartupAssetEntry now carries a vector of destPaths so the cancel path can clean up every partial file (audio batch + boot disk). - StartupDownloadDialog renders a per-kind sources blurb under the intro explaining that ROMs come from the AppleWin mirror, drive audio from OpenEmulator, and boot disks from Asimov, and that none of these are bundled with Casso. - RunStartupDownloader signature extended with offerBootDisk + diskDir + outBootDiskPath out-params. Main.cpp computes first-launch state (no --disk1, no remembered disk, machine has Disk ][ controller) and pipes the downloaded disk back into inoutDisk1Path so the legacy boot-disk picker short-circuits. SettingsPanel passes offerBootDisk=false (switch-machine flow never auto-downloads disks). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Group entries under headers (machine ROMs, Disk ][ audio, Boot disks). - ROMs locked-checked; audio and disk children are user-toggleable. - Status text and progress bars hidden until the user clicks Download. - Split Disk ][ audio into Shugart and Alps entries (one per mechanism). - Add ProDOS alongside DOS 3.3 as boot-disk options (DOS 3.3 default). - Intro text now names the actual machine (e.g. `Apple //e''). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
ShowStandaloneDialog hardcoded ChromeTheme::Skeuomorphic, so every pre-shell prompt (missing ROMs, drive-audio consent, boot-disk picker, unified startup downloader) ignored the user's persisted activeTheme. Plumb GlobalUserPrefs::activeTheme through the standalone-dialog call sites so the startup flow paints in the user's chosen theme (Skeuomorphic / DarkModern / RetroTerminal). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Covers set composition (ROM-only, audio-only, boot-disk-only, mixed, empty), insertion-order preservation across kinds, and default selectable/selected state for new entries. Inlines StartupDownloadSet::RequiresRoms() in the header so the test TU doesn't have to link the full dialog implementation. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Genericises the SettingsWindow chrome (titlebar + DX swap chain + nav layer + DPI + activation) into a reusable host that drives any IChromedPanelContent implementation. No consumers yet -- SettingsPanel retrofit and DiskIIDebugPanel scaffold follow. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Empty ChromedPanelWindow-hosted panel implementing both IDiskIIEventSink and IDriveAudioEventSink (no-op callbacks until T046). CASSO_LEGACY_DISKII_DEBUG_DIALOG compile-time switch (default ON) in EmulatorShell.cpp selects between the legacy dialog and the new panel; OpenDiskIIDebugDialog branches on it. Main-loop RenderFrame() hook gated on the same switch. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Pure ComputeDiskIIDebugPanelLayout() helper mirrors legacy DiskIIDebugDialog metrics (kRowHeight=22, kMargin=8, kRowGap=4 at 96 DPI) with DPI scaling. Cached in DiskIIDebugPanel::m_layout and recomputed on OnHostCreated / OnHostResize. 10 new layout-slot unit tests in DiskIIDebugPanelLayoutTests.cpp covering ordering, contiguity, raw-qt alignment, button row, ListView flex-fill, DPI scaling, and degenerate sizes. State TU remains Win32-free (SC-010). 1633/1633 tests pass. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Layout helper accepts top-offset so slots sit below the chrome title bar. - Panel owns DxUiPainter + DwriteTextRenderer + two Label widgets (Track:/Sector:). - Render() runs the full Begin/Paint/End pipeline: bind back-buffer text target lazily, clear to themed background, paint title bar through TitleBar::Paint, paint static labels, present. - LayoutLabels() re-anchors labels on resize or theme swap. - 1 new layout test (TopOffsetShiftsAllSlots); 1634/1634 green on ARM64 Debug. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Adds TextInput widget (selection, clipboard, keyboard nav) and wires the full DiskIIDebugPanel content: event-type/audio/raw-qt checkboxes, drive radio group, track/sector text filters with validation, pause/ clear buttons, and a virtualized event ListView. Implements all 18 IDiskIIEventSink and IDriveAudioEventSink overrides routing events through the ring + drain projection pipeline (legacy parity). Chrome shell forwards WM_CHAR to content via IChromedPanelContent::OnChar so text inputs receive typed characters. Legacy DiskIIDebugDialog still default-on via CASSO_LEGACY_DISKII_DEBUG_DIALOG until panel parity verification (T059). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Flips CASSO_LEGACY_DISKII_DEBUG_DIALOG to 0 and adds cycle-counter, uptime-anchor, and multi-controller-hint wiring to the panel branch in EmulatorShell. Legacy DiskIIDebugDialog code remains in source under the compile switch pending T059 cleanup commit. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
T059 cutover. The DX-themed DiskIIDebugPanel is now the sole Disk II debug surface; the 3000-line Win32 dialog implementation goes away along with the CASSO_LEGACY_DISKII_DEBUG_DIALOG compile switch and the twin m_diskIIDebugDialog member that shadowed the panel during the transition. MachineManager and EmulatorShell now reference m_diskIIDebugPanel directly; DiskIIDebugDialogState (FilterState, columns, predicate) remains as it backs both the panel and its tests. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
US6 (T039-T043). DebugConsolePanel hosts itself in the shared
ChromedPanelWindow chrome shell, exposes the same Log/LogConfig
contract the rest of the shell uses, and paints a themed monospace
log body with mouse-wheel + keyboard scrolling. Ctrl+C copies the
entire buffer to the clipboard; granular text selection is
deferred. EmulatorShell owns the panel via unique_ptr (lazy-created
on first Ctrl+D). Legacy DebugConsole.{h,cpp} deleted.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
T060-T065 merge gates. Bumps Version.h to 1.4.1364, renames the spec-011 CHANGELOG entry to the current version, adds the two new DX panel rewrites (DiskIIDebugPanel + DebugConsolePanel) to the Added list, refreshes the Deferred section to track T056-T058 + the granular-selection deferral, and bumps the test-count line to 1634/1634. Quickstart Phase P3 rewritten to match the shipped behavior (no compile-time switch, no column popup, etc). T060 (rg containment): only remaining MessageBoxW is the pre-shell fatal-error fallback in Main.cpp -- intentional last-resort path. T061 (code analysis): 0 warnings under MSVC /analyze. T062 (tests): 1634/1634 passing. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Closes the last four tasks of spec 011 (T043, T056-T058) and ships the
DiskIIDebugPanel polish that was previously deferred:
* New shared `PopupMenu` widget under `Casso/Ui/Widgets/` — themed
context menu with check glyph, keyboard navigation, and host-rect
clamping. Reusable from any panel that wants a DX-rendered context
menu without falling back to `CreatePopupMenu`.
* `ListView` gains per-column visibility (`SetColumnVisible` /
`ColumnVisible`) plus accessors needed for the popup (`ColumnCount`,
`ColumnAt`, `HeaderHeightPx`, `ShowHeader`). `ComputeColumnLayout`
zeros hidden columns' widths and skips stretch assignment.
* `ChromedPanelWindow` routes `WM_RBUTTONDOWN` to the content via the
new `IChromedPanelContent::OnRButtonDown` hook.
* `DiskIIDebugPanel`:
* Right-clicking inside the ListView header strip opens a column
popup; selection flips visibility and re-runs layout.
* Mouse / keyboard / paint route through the popup ahead of every
other widget while visible, and the tooltip suppresses itself so
the two overlays don't fight for the cursor.
* Tooltip integration completed: every filter, audio toggle, drive
radio, and track / sector edit surfaces an explanatory tooltip
after the standard hover dwell.
Manual quickstart walkthrough captured Debug Console and Disk II
Debug Panel screenshots under Skeuomorphic, DarkModern, and
RetroTerminal to verify FR-013 — chrome shell, monospace body,
themed palette, and full DiskIIDebugPanel layout (no overlap, all
six ListView columns visible) all render correctly per theme.
Tests: 1634/1634 passing. Code analysis: clean. ARM64 Debug build:
clean.
Co-authored-by: Copilot <noreply@github.com>
T041: DebugConsolePanel now supports click-drag and Shift+arrow text selection (Shift+Ctrl+Home/End to buffer extremes), Ctrl+A select-all, and Ctrl+C copy-selection to clipboard as CF_UNICODETEXT. Selection highlight paints under the text using the active theme's nav-hover colour. Empty-selection Ctrl+C is a no-op per spec. T055: DiskIIDebugPanel header click sorts by the clicked column; clicking the active column flips ascending/descending. All six columns participate. Cycle column uses length-then-lex (equivalent to numeric on comma-grouped uint strings). ListView gained HitTestHeaderColumn plus a ▲/▼ sort-indicator glyph in the active header. Build: 1634/1634 tests pass; code analysis 0 warnings / 0 errors under ARM64 Debug. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Code inspection confirmed T039, T040, T042, T044-T054, T059, and T060-T065 were already implemented in earlier commits but never had their checkboxes flipped. Bookkeeping only -- no code change. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…logs SettingsPanel was hardcoding a dark-navy background while DialogPrimitiveRenderer used theme.dropdownBgArgb, producing visibly different colors when stacked. Add panelBgArgb/panelEdgeArgb to ChromeTheme (with values for all three preset themes) and route both call sites through them. Settings popup now follows the active theme like everything else. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Switching machines (e.g. //e DOS 3.3 -> ][+) tore down the old Disk II controller and rebuilt an empty one. The previously mounted image was left orphaned in DiskImageStore (never bound to the new controller), so the boot ROM seeked to track 0, found nothing, and looped forever waiting for sector sync. User reported one head seek, then silence. Now MachineManager::SwitchMachine snapshots slot-6 source paths (drive 0 + drive 1) before teardown, then passes them to MountCommandLineDisks after the new controller is up. This matches the user's physical mental model: the disk stays in the drive across machine swaps. Re-mounting also auto-updates the new machine's per-machine saved-disk prefs via MountDiskInSlot6, so the disk persists across subsequent launches too. When no disk is mounted at switch time, the per-machine prefs lookup still kicks in. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Previously the slot-6 carry path called MountCommandLineDisks unconditionally on the new machine, relying on MountDiskInSlot6's nullptr-controller CBR to silently no-op when the destination machine lacked a Disk II. Make the intent explicit: if the new machine has no slot-6 controller (future non-Apple-II family), clear the carry strings so we don't even attempt the mount. User data is safe -- the source disk was already flushed before teardown. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Tooltip honours DPI (font, padding, border, anchor gap) and measures real text width. Widened filter checkbox / radio / raw-qt slot widths so labels stop wrapping. Bumped kColDriveWidth so the Drive header stops clipping. Added IChromedPanelContent::IsNonModal hook; DiskII debug + Debug console panels now pass nullptr as parent so they don't pin above Casso. Added theme.buttonIdle/Hover/Pressed/BorderArgb palette and switched Button defaults off the transparent sysButton chrome palette; Button now paints a 1dip themed border by default so buttons look like buttons. Renamed event list 'Wall' header to 'Time'. Guarded cross-machine disk carry on HasSlot6Controller (already shipped 389c85d; mentioned here for completeness). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…size, invalid detail, Drive label, default radio Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…e atop widget text Both DxUiPainter (geometry) and DwriteTextRenderer (text) batch their draws -- End/EndDraw flush ALL submissions to the RTV at once, regardless of submission order. The 0xFF tooltip background alpha alone wasn't enough: text from underlying widgets (e.g. the rawQt checkbox label) was still painting on top of the tooltip's opaque background. Fix: between the last widget paint and the tooltip/columnMenu paint in DiskIIDebugPanel::Render, cycle End/Begin on both renderers when an overlay is visible. The overlay's geometry then composites above all prior text. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…vigation Three deferred polish items from the round-1 issue list: 1. Mouse-wheel / trackpad scrolling. ListView now keeps the full filtered history (not just the visible tail), tracks an m_topRow + m_stickyTail pair, and ScrollByWheelDelta translates WHEEL_DELTA notches into row deltas. DiskIIDebugPanel overrides OnMouseWheel from IChromedPanelContent and forwards the delta to the list. 2. Vertical scrollbar. ListView::Paint draws a track + proportional thumb at the right edge whenever RowCount > VisibleRowCapacity. HitTestRow / HitTestHeaderColumn / HitTestColumnResize / ColumnEffectiveWidthPx subtract the scrollbar width from the column-layout extent so cells don't underlap the thumb. 3. Keyboard focus + Tab navigation. New SetFocusIndex / FocusCycle / ClearAllWidgetFocus helpers map 19 stops (Pause, Clear, 8 event checks, audio master + 4 sub-checks, rawQt check, drive radio group, track edit, sector edit). Tab / Shift+Tab cycle in OnKey, and OnLButtonDown sets focus to the hit widget. OnKey now also forwards to every widget's own OnKey so Enter/Space activate buttons, Space toggles checkboxes, arrows cycle radios. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…eservation Reshuffle the Disk II debug panel's focus index space so Tab follows a Z-pattern starting top-left (Motor checkbox) instead of Pause. Stops 0..18 cover the named widgets (event checks, audio master + subs, Drive radio, Track/Sector edits, raw-QT, Pause, Clear). Stops 19+ are dynamic per-visible-column: header[i] / divider[i|i+1] / ... / list, totalling 2 * VisibleColumnCount. Space sorts at a header stop; Left/Right resize the column to the left of a divider stop by 8dp; Up/Down/Home/End/PageUp/PageDown drive selection at the list stop. The ListView widget gains m_selectedRow / m_listFocused / m_focusedHeaderCol / m_focusedDividerCol and renders a row-selection fill (when focused) plus 1px header focus ring and 2px divider focus bar using the theme accent. SetSelectedRow auto-scrolls so the row is in view. DiskIIDebugPanel persists selection by event identity (m_listSelectedEventIndex into m_events). ApplyListSelection() is called after every filter/sort/clear rebuild and uses lower_bound to snap to the original event if visible, else to the largest still- visible index below it, else the smallest above, else clears. OnKey now routes input to the focused widget only -- the previous broadcast-to-all path swallowed arrow keys at the wrong widgets. FocusCycle wraps over TotalStopCount and honours Shift+Tab from the unfocused state by landing on the last stop. PushListViewRows now skips m_filteredIndices entries that exceed m_events.size() as defense in depth against any path that desyncs the deque and the filtered-index list. This was the most plausible candidate for the reported �ector subscript out of range debug assert in ARM64 Debug; with the new clear/rebuild ordering and the guard, the unguarded indexed access is gone. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…llbar - ListView: right-aligned header titles on the sort column now reserve room for the sort triangle so the two no longer overlap. - TextInput: single-line edits no longer wrap. DwriteTextRenderer gains an optional wrap flag (NO_WRAP) and PushClipRect/PopClipRect. TextInput tracks a per-widget pixel scroll offset, keeps the caret in view, and adjusts CaretFromX so clicks still hit the right character once scrolled. - ListView: scrollbar thumb is draggable with live scrolling. New HitTestScrollbarThumb/Track and BeginThumbDrag/UpdateThumbDrag/EndThumbDrag; the Disk II debug panel routes mouse events through them ahead of other hit-tests, with page-scroll on track clicks. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
… when master off Both checkbox rows now have a leading label of the same width so the checkbox columns line up. The audio master checkbox is relabelled 'All' (the row label says 'Audio events:' now), and its four sub-checkboxes disable when 'All' is unchecked. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
DiskIIDebugPanel was orphaned after the title-bar X destroyed its HWND -- the cached unique_ptr in EmulatorShell still held a non-null pointer with a dead handle, so the next Show() call no-op'd. Open path now treats Hwnd()==nullptr the same as panel==nullptr and reconstructs. Also removes the DX Debug Console panel (DebugConsolePanel.h/.cpp, IDM_HELP_DEBUG, Ctrl+D accelerator, Help menu entry, keymap dialog line, per-frame render hook). It carried no signal worth keeping -- DEBUGMSG already routes to the VS debugger and machine-config dumps duplicate the Hardware Info dialog. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Underline was positioned at y+lineH-1 -- the bottom of the inflated 22dp body line box -- leaving a ~6px gap below the 13dp text. Now positions it at y+fontPx+2dp so it tracks the glyph descender. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
# Conflicts: # CHANGELOG.md # Casso/Casso.vcxproj # Casso/Disk2DebugDialog.cpp # Casso/Disk2DebugDialog.h # Casso/EmulatorShell.cpp # Casso/EmulatorShell.h # Casso/Shell/MachineManager.cpp # Casso/Ui/Chrome/NavLayer.cpp # Casso/Window.h # CassoCore/Version.h # UnitTest/UnitTest.vcxproj
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
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.
Spec-011 themed DX dialogs replace every Win32 MessageBoxW / TaskDialogIndirect consumer (except the pre-shell EHM fallback in Main.cpp and the IFileOpenDialog disk picker). Includes the boot-disk MRU picker, the Disk2 debug panel (replacing the old DiskII debug dialog), and a wide tail of polish from screenshot rounds.
Merged origin/master (v1.5 quarter-track / copy-protection work + DiskII -> Disk2 rename) into this branch; HEAD's DiskII* spec-011 identifiers renamed to Disk2*.
Build: 0 warnings, 0 errors (including /analyze). Tests: 1653/1653 passing.