From 4f61953e1a1e300725eba459643cb310b641d3d6 Mon Sep 17 00:00:00 2001 From: Bill Date: Mon, 9 Feb 2026 13:04:58 -0700 Subject: [PATCH] Step 119: zoom controls --- PROGRESS.md | 5 ++++- editor/CMakeLists.txt | 4 ++++ editor/src/ZoomUtils.h | 14 ++++++++++++++ editor/src/main.cpp | 18 ++++++++++++++++++ editor/tests/step119_test.cpp | 27 +++++++++++++++++++++++++++ sprint4_plan.md | 2 +- 6 files changed, 68 insertions(+), 2 deletions(-) create mode 100644 editor/src/ZoomUtils.h create mode 100644 editor/tests/step119_test.cpp diff --git a/PROGRESS.md b/PROGRESS.md index 6dbbe1d..ddaa4c4 100644 --- a/PROGRESS.md +++ b/PROGRESS.md @@ -222,6 +222,7 @@ All 38 steps implemented and passing. Each step has a corresponding test (`step1 - [x] Step 116: **IMPLEMENTED** — Project save/load (.whetstone) with AST serialization (4/4 tests pass) - [x] Step 117: **IMPLEMENTED** — Session persistence (layout, buffers, cursors, folds) (5/5 tests pass) - [x] Step 118: **IMPLEMENTED** — Settings panel + persistence (11/11 tests pass) +- [x] Step 119: **IMPLEMENTED** — Zoom controls and status bar indicator (5/5 tests pass) --- @@ -323,6 +324,7 @@ vcpkg's imgui 1.91.9 removed the `sdl2-binding` feature (only `sdl3-binding` exi **Step 116:** Compile and pass (4/4) **Step 117:** Compile and pass (5/5) **Step 118:** Compile and pass (11/11) +**Step 119:** Compile and pass (5/5) --- @@ -374,7 +376,7 @@ vcpkg's imgui 1.91.9 removed the `sdl2-binding` feature (only `sdl3-binding` exi ## What's Next -Sprint 4 in progress. Step 118 (settings panel) done. Next: Step 119 (zoom). +Sprint 4 in progress. Step 119 (zoom) done. Next: Step 120 (undo/redo rework). --- @@ -454,3 +456,4 @@ Sprint 4 in progress. Step 118 (settings panel) done. Next: Step 119 (zoom). | 2026-02-09 | Codex | Step 116: Project save/load (.whetstone) with AST serialization. 4/4 tests pass. | | 2026-02-09 | Codex | Step 117: Session persistence (layout, buffers, cursors, folds). 5/5 tests pass. | | 2026-02-09 | Codex | Step 118: Settings panel + persistence. 11/11 tests pass. | +| 2026-02-09 | Codex | Step 119: Zoom controls and status bar indicator. 5/5 tests pass. | diff --git a/editor/CMakeLists.txt b/editor/CMakeLists.txt index ce16488..517720b 100644 --- a/editor/CMakeLists.txt +++ b/editor/CMakeLists.txt @@ -634,6 +634,10 @@ add_executable(step118_test tests/step118_test.cpp) target_include_directories(step118_test PRIVATE src) target_link_libraries(step118_test PRIVATE nlohmann_json::nlohmann_json) +add_executable(step119_test tests/step119_test.cpp) +target_include_directories(step119_test PRIVATE src) +target_link_libraries(step119_test PRIVATE nlohmann_json::nlohmann_json) + find_package(SDL2 CONFIG REQUIRED) find_package(OpenGL REQUIRED) find_package(glad CONFIG REQUIRED) diff --git a/editor/src/ZoomUtils.h b/editor/src/ZoomUtils.h new file mode 100644 index 0000000..4fa2e46 --- /dev/null +++ b/editor/src/ZoomUtils.h @@ -0,0 +1,14 @@ +#pragma once +// Step 119: Zoom utilities + +inline int clampFontSize(int size, int minSize = 12, int maxSize = 24) { + if (size < minSize) return minSize; + if (size > maxSize) return maxSize; + return size; +} + +inline int zoomPercent(int fontSize, float baseFontSize) { + if (baseFontSize <= 0.0f) return 100; + float pct = (fontSize / baseFontSize) * 100.0f; + return (int)(pct + 0.5f); +} diff --git a/editor/src/main.cpp b/editor/src/main.cpp index e9756c1..a1839e2 100644 --- a/editor/src/main.cpp +++ b/editor/src/main.cpp @@ -48,6 +48,7 @@ #include "Orchestrator.h" #include "ProjectManager.h" #include "SessionManager.h" +#include "ZoomUtils.h" #include "ast/Serialization.h" #include "ast/Generator.h" #include "ast/Annotation.h" @@ -1962,6 +1963,17 @@ int main(int, char**) { state.commandSelected = 0; } + auto applyFontSize = [&](int newSize) { + newSize = clampFontSize(newSize); + state.settings.setFontSize(newSize); + io.FontGlobalScale = newSize / baseFontSize; + state.saveSettingsToDisk(); + }; + + if ((sdlMod & KMOD_CTRL) && sym == SDLK_0) { + applyFontSize((int)baseFontSize); + } + if (key != 0 && mods != WMOD_NONE) { KeyCombo combo{key, mods}; std::string action = state.keys.getAction(combo); @@ -1979,6 +1991,8 @@ int main(int, char**) { std::string lang = state.active() ? state.active()->language : "python"; state.createBuffer(state.makeUntitledName(), "", lang); } + else if (action == "view.zoomIn") applyFontSize(state.settings.getFontSize() + 1); + else if (action == "view.zoomOut") applyFontSize(state.settings.getFontSize() - 1); } } } @@ -4009,6 +4023,10 @@ int main(int, char**) { ImGui::Text("Keys: %s", KeybindingManager::profileName(state.keys.getProfile())); ImGui::SameLine(0, 30); + // Zoom + ImGui::Text("Zoom: %d%%", zoomPercent(state.settings.getFontSize(), baseFontSize)); + ImGui::SameLine(0, 30); + // Modified indicator if (state.active() && state.active()->modified) ImGui::Text("Modified"); diff --git a/editor/tests/step119_test.cpp b/editor/tests/step119_test.cpp new file mode 100644 index 0000000..bff4f98 --- /dev/null +++ b/editor/tests/step119_test.cpp @@ -0,0 +1,27 @@ +// Step 119 TDD Test: Zoom utilities +#include "ZoomUtils.h" +#include + +static void expect(bool cond, const std::string& name, int& passed, int& failed) { + if (cond) { + std::cout << "Test " << (passed + failed + 1) << " PASS: " << name << "\n"; + ++passed; + } else { + std::cout << "Test " << (passed + failed + 1) << " FAIL: " << name << "\n"; + ++failed; + } +} + +int main() { + int passed = 0; + int failed = 0; + + expect(clampFontSize(10) == 12, "clamp low", passed, failed); + expect(clampFontSize(30) == 24, "clamp high", passed, failed); + expect(clampFontSize(18) == 18, "clamp ok", passed, failed); + expect(zoomPercent(15, 15.0f) == 100, "zoom 100", passed, failed); + expect(zoomPercent(18, 15.0f) == 120, "zoom 120", passed, failed); + + std::cout << "\n=== Step 119 Results: " << passed << " passed, " << failed << " failed ===\n"; + return failed == 0 ? 0 : 1; +} diff --git a/sprint4_plan.md b/sprint4_plan.md index 3fa1b3d..29d0c07 100644 --- a/sprint4_plan.md +++ b/sprint4_plan.md @@ -380,7 +380,7 @@ AST extensions for Sprint 5. keybinding profile. Persisted to `~/.whetstone/settings.json`. *New:* `SettingsManager.h` -- [ ] **Step 119: Zoom** +- [x] **Step 119: Zoom** Ctrl+= zoom in, Ctrl+- zoom out, Ctrl+0 reset. Scales the editor font size dynamically. Status bar shows current zoom level. *Modifies:* `main.cpp`