Files
whetstone_DSL/editor/src/FirstRunWizard.h
Bill 1696b92bb8 Add Sprints 46-59: governance, porting foundation, and language graduation prep (Steps 689-828)
Sprints 46-58 implement the cross-language porting foundation: language-to-IR
adapters, equivalence checking, gate validation, legacy ingestion, managed/dynamic
families, low-level/logic-actor semantics, debug workflow tooling, AST-native
family tools, Rust/CPP raising tools, system-level orchestration, query family,
and porting gates. Sprint 59 adds the governance layer (policy packs, review
boards, waiver packets, ambiguity triage, decision ledger) with the
whetstone_review_porting_decision MCP tool.

Also includes: sprint plans 46-130, MCP taskitem pipeline scripts,
CLAUDE.md, docs, and full test matrix (steps 689-828).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-22 13:18:10 -07:00

131 lines
4.9 KiB
C++

#pragma once
#include "imgui.h"
#include "ThemeEngine.h"
#include "EditorState.h"
#include <vector>
struct FirstRunWizardState {
bool open = false;
int step = 0;
int layoutIndex = 0;
int themeIndex = 0;
int keyIndex = 0;
int modeIndex = 0;
};
static void renderFirstRunWizard(EditorState& state, FirstRunWizardState& wizard) {
if (!wizard.open) return;
ImGui::SetNextWindowSize(ImVec2(520, 360), ImGuiCond_FirstUseEver);
if (!ImGui::Begin("Setup Wizard", &wizard.open, ImGuiWindowFlags_NoResize)) {
ImGui::End();
return;
}
const char* layoutLabels[] = {"VSCode", "Emacs", "JetBrains"};
const LayoutPreset layoutValues[] = {LayoutPreset::VSCode, LayoutPreset::Emacs, LayoutPreset::JetBrains};
const char* keyLabels[] = {"VSCode", "JetBrains", "Emacs"};
const KeybindingProfile keyValues[] = {KeybindingProfile::VSCode, KeybindingProfile::JetBrains, KeybindingProfile::Emacs};
std::vector<std::string> themeNames = ThemeEngine::instance().listThemes();
if (themeNames.empty()) {
themeNames = {"Whetstone Dark", "Whetstone Light"};
}
int maxThemes = std::min(4, (int)themeNames.size());
if (wizard.step == 0) {
ImGui::TextUnformatted("Welcome to Whetstone");
ImGui::Separator();
ImGui::TextWrapped("This short wizard helps you pick a layout, theme, and keybindings.");
} else if (wizard.step == 1) {
ImGui::TextUnformatted("Choose a layout preset");
ImGui::Separator();
for (int i = 0; i < IM_ARRAYSIZE(layoutLabels); ++i) {
if (ImGui::RadioButton(layoutLabels[i], wizard.layoutIndex == i)) {
wizard.layoutIndex = i;
}
}
} else if (wizard.step == 2) {
ImGui::TextUnformatted("Choose a theme");
ImGui::Separator();
for (int i = 0; i < maxThemes; ++i) {
if (ImGui::RadioButton(themeNames[i].c_str(), wizard.themeIndex == i)) {
wizard.themeIndex = i;
}
}
} else if (wizard.step == 3) {
ImGui::TextUnformatted("Choose keybindings");
ImGui::Separator();
for (int i = 0; i < IM_ARRAYSIZE(keyLabels); ++i) {
if (ImGui::RadioButton(keyLabels[i], wizard.keyIndex == i)) {
wizard.keyIndex = i;
}
}
} else if (wizard.step == 4) {
ImGui::TextUnformatted("Choose editor mode");
ImGui::Separator();
ImGui::TextWrapped("Text mode is recommended for a familiar editor experience. "
"Structured mode enables AST-driven features.");
if (ImGui::RadioButton("Text (Recommended)", wizard.modeIndex == 0)) {
wizard.modeIndex = 0;
}
if (ImGui::RadioButton("Structured", wizard.modeIndex == 1)) {
wizard.modeIndex = 1;
}
} else if (wizard.step == 5) {
ImGui::TextUnformatted("Get started");
ImGui::Separator();
if (ImGui::Button("Open Example Project")) {
state.notify(NotificationLevel::Info, "Example project not bundled yet.");
}
if (ImGui::Button("Open Folder")) {
auto path = FileDialog::openFolder({"Open Folder", state.workspaceRoot});
if (!path.empty()) {
std::string error;
if (!state.setWorkspaceRoot(path, &error)) {
state.notify(NotificationLevel::Error,
"Failed to open folder: " + error);
}
}
}
if (ImGui::Button("New File")) {
std::string lang = state.active() ? state.active()->language : "python";
state.createBuffer(state.makeUntitledName(), "", lang, state.defaultBufferMode());
}
}
ImGui::Separator();
if (wizard.step > 0) {
if (ImGui::Button("Back")) {
wizard.step = std::max(0, wizard.step - 1);
}
ImGui::SameLine();
}
if (wizard.step < 5) {
if (ImGui::Button("Next")) {
wizard.step = std::min(5, wizard.step + 1);
}
} else {
if (ImGui::Button("Finish")) {
if (wizard.layoutIndex >= 0 && wizard.layoutIndex < IM_ARRAYSIZE(layoutValues)) {
state.ui.layoutPreset = layoutValues[wizard.layoutIndex];
}
if (wizard.keyIndex >= 0 && wizard.keyIndex < IM_ARRAYSIZE(keyValues)) {
state.keys.setProfile(keyValues[wizard.keyIndex]);
state.registerCommands();
}
if (wizard.themeIndex >= 0 && wizard.themeIndex < maxThemes) {
state.settings.setTheme(themeNames[wizard.themeIndex]);
ThemeEngine::instance().applyTheme(themeNames[wizard.themeIndex]);
}
state.settings.setDefaultBufferMode(wizard.modeIndex == 1 ? "structured" : "text");
state.saveSettingsToDisk();
wizard.open = false;
state.ui.showFirstRunWizard = false;
}
}
ImGui::End();
}