Controllers
Controllers sit between ImGui callbacks and core services. They mutate state, coordinate storage, and emit AppEvents.
flowchart LR
Panels[UI callbacks] --> Runtime[AppRuntime]
Runtime --> Controllers[Controllers]
Controllers --> Services[Core services and managers]
Controllers --> Events[AppEvents]
Events --> Runtime
Controller Reference
| Controller | Owns or coordinates | Main outputs |
|---|---|---|
ElementEditController |
Add top goal, add child, remove selected, remove confirmation state. | TreeDirtyEvent, DocumentDirtyEvent, selection/status events. |
AiReviewController |
AI review request assembly, debug modal state, async task polling, response parsing. | AI ProblemItem records, status events. |
ReviewController |
Review item persistence, dirty state, delete/resolve workflow. | ReviewItemsDirtyEvent, review item file writes, and review-problem resync through AppRuntime. |
ProposalController |
Proposal manager, creator mode, preview model, generated id map. | Proposal draft/preview state. |
ProjectController |
File buffers, directory scan state, recent-project preferences, create/open modal state. | UI workflow state. |
ModalCoordinator |
Cross-cutting modal/window flags and close requests. | Modal visibility and close coordination. |
Dependencies
flowchart TD
AppRuntimeState --> ElementEditController
AppRuntimeState --> AiReviewController
AppRuntimeState --> ReviewController
AppRuntimeState --> ProposalController
AppRuntimeState --> ProjectController
AppRuntimeState --> ModalCoordinator
ElementEditController --> ElementFactory[core::ElementFactory functions]
AiReviewController --> AiService[ai::AiService]
AiReviewController --> AiTaskRunner[ai::AiTaskRunner]
AiReviewController --> Problems[core::ProblemsManager]
ReviewController --> ReviewItemManager[core::reviews::ReviewItemManager]
ProposalController --> ProposalManager[core::reviews::ReviewProposalManager]
ProjectController --> RecentProjects[recent project helpers]
ModalCoordinator --> Events[app::AppEvents]
Add Element Flow
sequenceDiagram
participant UI as Tree/canvas/menu
participant Runtime as AppRuntime
participant Controller as ElementEditController
participant Factory as core::AddChildElement
participant Parser as parser::AssuranceCase
participant Sacm as sacm::AssuranceCasePackage
participant Events as AppEvents
UI->>Runtime: add_child(kind)
Runtime->>Controller: AddChildToSelected(model, package, selected_id, kind)
Controller->>Factory: AddChildElement(...)
Factory->>Parser: append element and relationship
Factory->>Sacm: append typed element and relationship
Controller->>Events: DocumentDirtyEvent
Controller->>Events: TreeDirtyEvent
Remove Element Flow
sequenceDiagram
participant UI as Context menu
participant Controller as ElementEditController
participant Factory as core element factory
participant Events as AppEvents
UI->>Controller: RemoveSelected(id, mode)
Controller->>Factory: PlanRemoval(model, id, mode)
alt multiple affected elements
Controller-->>UI: show remove confirmation
UI->>Controller: ConfirmPendingRemoval()
end
Controller->>Factory: RemoveElement(model, package, id, mode)
Controller->>Events: DocumentDirtyEvent
Controller->>Events: TreeDirtyEvent
Selection Flow
sequenceDiagram
participant View as Tree/canvas/problems
participant Events as AppEvents
participant Runtime as Runtime subscriber
participant State as ui::UiState
View->>Events: SelectionChangedEvent(element_id)
Events->>Runtime: handle event
Runtime->>State: selected_element_id = element_id
Runtime->>Events: CenterRequestEvent when needed
AI Review Flow
sequenceDiagram
participant UI as Problems panel / context action
participant Controller as AiReviewController
participant Catalog as SCCG profile catalog
participant Builder as ai::BuildAiReviewPayload
participant Data as ai::CollectAiReviewDataPackages
participant Service as ai::AiService
participant Runner as ai::AiTaskRunner
participant Parser as ai::ParseAiReviewResponse
participant Problems as ProblemsManager
participant Draft as DraftWorkspaceStore
UI->>Draft: materialize working model
Draft-->>UI: working case + tree
UI->>Controller: BeginReviewForSelection(working case, tree, element_id)
Controller->>Catalog: select unique profile for element role
Controller->>Builder: build selected, parent, and children payload
Controller->>Data: collect profile-required data packages
Controller-->>UI: request ready in AI Debug panel
UI->>Controller: StartPendingRequest()
Controller->>Runner: RunGenerate(service.Generate(request))
Controller->>Controller: PollTask() each frame
Runner-->>Controller: AiResponse
Controller->>Parser: ParseAiReviewResponse(response, element_id)
Parser-->>Controller: findings + suggested text
Controller->>Problems: AddOrUpdateProblem(problem)
Controller-->>Draft: stage ready SCCG correction groups
Controllers should stay thin. Core rules belong in src/core, parser rules in src/parser, SACM round-trip rules in src/legacy_sacm, and provider-specific AI behavior in src/ai.
Two current exceptions are worth calling out:
ui::panels::ShowElementPanel()edits the active parser element directly, then AppRuntime emits dirty events.ReviewItemsDirtyEventis not storage-only. AppRuntime listens for it and rebuilds review-derived problems inProblemsManager.