14 KiB
Sprint 8: Refactor & UX Polish — Plan
Goal: Make Whetstone feel like a real editor out of the box. Fix the critical EditorState.h architecture violation, make text-first the default experience, properly dock panels on first launch, and add visual polish that shows off Dear ImGui capabilities.
Prerequisites: Sprint 7 complete (234 steps). All agent tooling and MCP infrastructure in place.
Key themes:
- Refactor EditorState.h (3,107 lines → multiple focused headers)
- Text-first default experience
- Proper DockBuilder layout on first launch
- Branded splash screen
- Visual effects (whetstone grinding sparks)
- Visual shortcut representation language
Phase 8a: Refactor EditorState.h (Steps 235–240)
EditorState.h is 3,107 lines (5.2x over the 600-line limit). Split it into domain-specific headers following the Sprint 6 panel extraction pattern.
-
Step 235: Extract RPC handler to AgentRPCHandler.h Move
processAgentRequest()and all its JSON-RPC method handlers into a new header. This is the single largest block (~500+ lines) added across Sprints 5–7.- Free function:
json processAgentRequest(EditorState&, const json&) - Includes all method dispatch (getAST, applyMutation, runPipeline, etc.)
- EditorState keeps a one-liner that delegates to it
New:
editor/src/AgentRPCHandler.h
- Free function:
-
Step 236: Extract buffer operations to BufferOps.h Move file/buffer operations out of EditorState:
doOpen,doSave,doClose,createBuffer,makeUntitledNamehandleFileChanges,refreshBuildSystem- File watcher logic, auto-save logic
- Recent files management
New:
editor/src/BufferOps.h
-
Step 237: Extract editing operations to EditOps.h Move text editing, undo/redo, and navigation:
doUndo,doRedo,doFindNext,doReplacenavigateToTarget,goToLine- Multi-cursor operations
- Clipboard operations
New:
editor/src/EditOps.h
-
Step 238: Extract LSP and diagnostics to LspOps.h Move LSP client management and diagnostic aggregation:
pollLspMessages,flushLspDidChangepublishDiagnosticshandling- Whetstone diagnostic merging
- LSP initialization and shutdown
New:
editor/src/LspOps.h
-
Step 239: Extract Emacs integration to EmacsOps.h Move Emacs-specific operations:
handleEmacsKeyChord,refreshEmacsModeLineupdateEmacsFunctionIndex- Emacs buffer sync, package queries
New:
editor/src/EmacsOps.h
-
Step 240: Verify EditorState.h under 600 lines + refactor tests After extraction, EditorState.h should be a thin shell:
- State member variables and sub-state includes
init(),active(),notify()convenience methods- Delegation calls to extracted headers Tests:
- EditorState.h is under 600 lines
- All extracted headers are under 600 lines
- No function exceeds 80 lines
- Existing step206_test and step213_test still pass
file_limits_testpasses with new headers added New:step240_test.cpp
Phase 8b: Text-First Default & Dock Layout (Steps 241–244)
Make the editor feel familiar on first launch — a normal text editor with optional structured features.
-
Step 241: Text-first default mode Change the default buffer mode from
StructuredtoText:BufferManager::BufferModedefault →TextinBufferInfoandopenBuffer()getBufferMode()fallback →Text- First-run wizard: add "Editor Mode" step (Text recommended, Structured for power users)
- Welcome screen tips updated to mention mode toggle
- Settings:
defaultBufferModepreference (text/structured) Modifies:BufferManager.h,FirstRunWizard.h,WelcomeScreen.h
-
Step 242: DockBuilder initial layout Apply the LayoutManager preset using ImGui DockBuilder on first launch:
- On first run (no session), call
ImGui::DockBuilderAddNode+DockBuilderSplitNode - VSCode preset: Explorer 20% left, Editor 60% center, Bottom panel 20%
- Panels docked by name to the correct dock node IDs
- Only runs once — after that, imgui.ini state takes over
- Layout reset action in menu: "View → Reset Layout" re-applies DockBuilder
Modifies:
main.cpp,LayoutManager.h
- On first run (no session), call
-
Step 243: Clean first-launch experience Polish the out-of-box experience:
- Window starts maximized (already done:
SDL_WINDOW_MAXIMIZED) - Welcome tab opens in the editor area (not floating)
- Explorer panel shows "Open Folder" prompt if no workspace
- Status bar shows "Text Mode" / "Structured Mode" indicator
- Bottom panel starts collapsed (user expands when needed)
Modifies:
main.cpp,panels/EditorPanel.h,panels/StatusBarPanel.h
- Window starts maximized (already done:
-
Step 244: First-launch UX tests Tests verifying default experience:
- New buffers default to Text mode
- Text mode hides AST-specific UI (annotation gutter, AST tab)
- Structured mode shows full UI
- Mode toggle works and persists
- LayoutManager preset data matches DockBuilder application
- Settings
defaultBufferModepreference respected New:step244_test.cpp
Phase 8c: Splash Screen & Branding (Steps 245–247)
A branded splash screen and polished startup feel.
-
Step 245: Startup splash overlay Render a branded splash on launch before editor loads:
- Centered overlay: "Whetstone" logo text + version
- Subtle animation (fade in, maybe spark trail — see Phase 8d)
- Shows for ~1.5 seconds or until first interaction
- "Loading..." progress text during init
- Rendered as an ImGui overlay window (fullscreen, no decorations)
- Configurable: "Show splash on startup" setting
Modifies:
main.cppNew:editor/src/SplashScreen.h
-
Step 246: Bottom notification bar A persistent slim bar at the bottom of the splash / welcome screen:
- Shows tips, version info, or "What's New" on first launch after update
- Can show keyboard shortcut of the day
- Dismissable, remembers dismissed state
- Separate from status bar — this is for onboarding/tips only
Modifies:
panels/StatusBarPanel.hor newpanels/TipBar.h
-
Step 247: Splash and branding tests
- Splash state initializes correctly
- Splash dismisses after timeout or interaction
- Splash respects "don't show" setting
- Tip bar content rotates and dismisses persist
New:
step247_test.cpp
Phase 8d: Visual Effects — Whetstone Sparks (Steps 248–250)
Show off Dear ImGui's drawing capabilities with a signature visual effect: grinding sparks flying from a whetstone, rendered as an overlay.
-
Step 248: Particle system engine A lightweight 2D particle system using ImGui's
ImDrawList:Particlestruct: position, velocity, lifetime, color, sizeParticleEmitter: spawn rate, direction cone, speed range, color gradientParticleSystem: update (gravity, fade, lifetime), render viaGetForegroundDrawList()- Configurable: max particles, gravity, wind
- Performance-safe: capped at 200 particles, skipped if reduce-motion enabled
New:
editor/src/ParticleSystem.h
-
Step 249: Whetstone spark effect Specific spark configuration for the whetstone theme:
- Sparks fly from a configurable origin (e.g., bottom-left corner or cursor position)
- Orange/yellow/white color gradient fading to dark
- Short-lived particles (0.3–0.8s) with gravity pulling down
- Sparks rendered on the foreground draw list (over all windows)
- Triggered on: splash screen, save action, build success, or manual toggle
- "Sparks" toggle in View menu and settings
New:
editor/src/SparkEffect.hModifies:main.cpp
-
Step 250: Particle system tests
- Particle spawn and lifetime decay work correctly
- Dead particles are recycled
- Reduce-motion setting disables particles
- Particle count stays within cap
- Spark effect produces particles with correct color range
New:
step250_test.cpp
Phase 8e: Visual Shortcut Representation (Steps 251–254)
Visual encoding of keyboard shortcuts as modifier-box glyphs. Each key is a letter/symbol inside a square where the four edges encode modifiers:
┌───┐ ╔───┐ ╔───╗ ╔───╗
│ K │ ║ K │ ║ K ║ ║ K ║
└───┘ ╚───┘ ╚───╝ ╚═══╝
(none) Ctrl+K Ctrl+Shift+K All mods
- Left edge = Ctrl — bright when active, dim when inactive
- Bottom edge = Alt
- Right edge = Shift
- Top edge = Win/Super/Meta
Active modifier = bright white/accent line. Inactive = low-light gray. The glyph is overlaid on any widget — buttons, icons, tabs, panels. Every interactive element can show its shortcut visually, enabling mouse-free discovery. Since ImGui is immediate mode, glyphs update instantly when shortcuts are reassigned by external tools or IPC.
-
Step 251: Modifier-box glyph renderer Core rendering engine for the visual shortcut encoding:
ModifierBoxGlyphstruct: key character/label, 4 modifier flags (ctrl, alt, shift, super)renderModifierBox(ImDrawList*, ImVec2 pos, float size, ModifierBoxGlyph, theme): draws a square with 4 independently styled edges + centered key label- Active edge: bright color (theme accent or white), 2px line
- Inactive edge: dim color (theme's muted gray), 1px line
- Key label: monospace font, centered in box
- Scalable:
sizeparameter controls glyph dimensions (respects zoom) - Theme-aware: colors from ThemeEngine (active edge, inactive edge, label, background)
- Chord sequences: multiple boxes with
>arrow separator - Supports special key labels: "⏎" (Enter), "⇥" (Tab), "⎋" (Esc), "⌫" (Backspace),
"↑↓←→" (arrows), mouse button glyphs, scroll wheel
New:
editor/src/ModifierBoxGlyph.h
-
Step 252: Widget shortcut overlay system Overlay modifier-box glyphs on any ImGui widget:
WidgetShortcutOverlaysystem: registry mapping widget IDs → shortcut glyphsregisterWidgetShortcut(widgetId, KeyCombo)→ stores glyph datarenderWidgetOverlay(ImDrawList*, ImRect widgetBounds)→ draws glyph in corner or center of widget (configurable placement: corner, center, beside)- Auto-detect: if a KeybindingManager action maps to a widget, overlay appears
- Visibility modes: always, on hover, on Alt hold, never
- Glyph placement: inside widget (bottom-right corner default) or beside label
- Non-interactive: overlay doesn't consume clicks
New:
editor/src/WidgetShortcutOverlay.h
-
Step 253: Integration across all panels + dynamic reassignment API Wire the overlay system into every panel and expose it for external control:
- Menu bar items: glyph beside each menu action
- Toolbar buttons: glyph overlay on each button
- Command palette: glyph column replaces text shortcuts
- Explorer panel: glyph on "New File", "New Folder" actions
- Tab bar: glyph on tab switch shortcuts (Ctrl+1..9)
- Shortcut reference panel: full glyph rendering instead of text
- Dynamic reassignment API (for external tools / window manager):
setWidgetShortcut(widgetId, KeyCombo)via JSON-RPCgetWidgetShortcuts()→ returns all widget→shortcut mappingsclearWidgetShortcut(widgetId)→ removes overlay- These methods added to
processAgentRequest(or new IPC channel)
- Settings: "Show shortcut glyphs" toggle, placement preference, visibility mode
Modifies:
panels/MenuBarPanel.h,panels/EditorPanel.h,panels/BottomPanel.h,panels/ExplorerPanel.h,ShortcutReference.h,WelcomeScreen.h,EditorState.h
-
Step 254: Shortcut glyph tests
- Modifier-box renders correct edges for each modifier combination (16 combos)
- Inactive edges are dim, active edges are bright
- Key label is centered in the box
- Chord sequences render as multiple boxes with separator
- Special key labels render correctly (Enter, Tab, arrows, mouse)
- Widget overlay appears at correct position relative to widget bounds
- Dynamic reassignment via API updates glyph immediately
- Visibility modes work (always, hover, alt-hold, never)
- Theme change updates glyph colors
- Zoom scaling applies to glyph size
New:
step254_test.cpp
Summary
| Phase | Steps | Description |
|---|---|---|
| 8a | 235–240 | Refactor EditorState.h (3,107 → <600 lines each) |
| 8b | 241–244 | Text-first default + DockBuilder layout |
| 8c | 245–247 | Splash screen & branding |
| 8d | 248–250 | Whetstone spark particle effects |
| 8e | 251–254 | Modifier-box shortcut glyphs + widget overlay system |
Total: 20 steps across 5 phases.
Architecture Notes
- Extraction pattern: Same as Sprint 6 panel extraction. Free functions
taking
EditorState&as first parameter. EditorState becomes a thin coordinator that includes and delegates. - 600-line limit enforced:
file_limits_testmust pass after Phase 8a. - Particle system: Uses
ImGui::GetForegroundDrawList()for overlay rendering. No OpenGL calls — pure ImDrawList for portability. - Reduce-motion: All animations and particles respect the existing
settings.getReduceMotion()flag. - Modifier-box glyphs: Rendered with
ImDrawList::AddLinefor edges andAddTextfor key labels. Each edge independently styled. The overlay system usesImGui::GetForegroundDrawList()to render above widgets without interfering with widget interaction. External tools can reassign shortcuts via JSON-RPC, and glyphs update on the next frame (immediate mode). - No new dependencies: Everything uses existing ImGui, SDL2, nlohmann-json.
Sprint 9 Preview (for planning)
Sprint 9: Production Integration & Real-World Testing
- End-to-end testing with real LLM agents (Claude, GPT-4, Llama)
- Multi-file project support (project-wide AST, cross-file references)
- Git integration (diff view, blame, branch-aware sessions)
- Performance profiling with real workloads
- New language support (Phase A: PHP, C#, Kotlin)
- Production packaging and stable release