English version: ARCHITECTURE.md.
ImGuiX сочетает подход Immediate Mode GUI из Dear ImGui с классическими объектно‑ориентированными паттернами. Фреймворк организует приложение UI в чётко определённые компоненты и каналы взаимодействия, благодаря чему большие проекты остаются поддерживаемыми.
.
├── include/ # публичные заголовки
│ └── imguix/ # основные заголовки библиотеки
│ ├── config/ # вспомогательные настройки
│ ├── controllers/ # утилиты контроллеров
│ ├── core/ # базовые модули фреймворка
│ │ ├── application/ # приложение и контекст
│ │ ├── controller/ # базовый класс контроллера
│ │ ├── events/ # встроенные типы событий
│ │ ├── fonts/ # менеджер шрифтов
│ │ ├── i18n/ # интернационализация
│ │ ├── model/ # базовые классы моделей
│ │ ├── notify/ # уведомления
│ │ ├── options/ # хранилище опций
│ │ ├── pubsub/ # шина событий
│ │ ├── resource/ # реестр ресурсов
│ │ ├── themes/ # менеджер тем
│ │ └── window/ # интерфейсы окон
│ ├── extensions/ # утилитарные расширения
│ ├── themes/ # встроенные темы
│ ├── utils/ # вспомогательные функции
│ ├── widgets/ # переиспользуемые виджеты
│ └── windows/ # утилиты для окон
├── docs/ # документация проекта
├── examples/ # примеры приложений
│ └── quickstart/ # минимальный стартовый проект
├── libs/ # включённые зависимости
├── src/ # исходники библиотеки
└── tests/ # тесты и демо
- Application — владеет глобальными сервисами и главным циклом.
- WindowManager — создаёт и отслеживает окна.
- WindowInstance — представляет отдельное окно и его контекст рендеринга.
- Controller — объединяет покадровую логику и отрисовку.
- FeatureModel — лёгкая модель, принадлежащая контроллеру и хранящаяся в реестре.
- Model — пользовательские данные или бэкенды вроде
OptionsStore. - EventBus — асинхронный узел Publisher–Subscriber для развязанного обмена.
- ResourceRegistry — потокобезопасный доступ к общим ресурсам (шрифты, темы, виджеты и т.п.).
- Immediate‑Mode MVC:
WindowInstanceвыступает в роли View, подклассыControllerсовмещают логику и отображение, а модели хранят постоянное состояние. - Событийное взаимодействие: компоненты отправляют события в
EventBus; слушатели получают уведомления во времяEventBus::process(). - Граница model/controller: app-level
Modelдолжен публиковать DTO-события черезEventBus; не передавайте такие модели напрямую в окна и контроллеры как зависимости владения или ссылки. - Локальные модели контроллера: контроллеры могут хранить небольшие модели-фичи в типобезопасном реестре; они выполняются в UI-потоке и не вызывают ImGui напрямую.
- Жизненный цикл / Template Method: окна и контроллеры предоставляют хуки
onInit,drawContentиdrawUi, вызываемые циклом приложения в фиксированном порядке. - Фабрики: контроллеры и модели создаются через фабричные функции.
WindowInstance::createController<T>()возвращает ограниченныйWindowInterface&, сохраняя инварианты. - Стратегии и расширяемость: темы, шрифты и виджеты регистрируются динамически.
StrategicControllerвыбирает стратегии, аExtendedControllerагрегирует дочерние элементы. - Посредник:
EventMediatorупрощает управление подписками для всех контроллеров и моделей. - Реестр ресурсов: почти синглтон‑реестр; повторная регистрация одного типа вызывает ошибку.
- Контракт событий: каждое событие наследует
Pubsub::Eventи реализует методыtype()иname(). - Ограничения моделей: прямые синхронные вызовы
notifyудалены; внеprocess()используйтеnotifyAsync. Внутриprocess()доступен переданныйSyncNotifier. - Разделение состояния: app-wide persistent state и shared services держите
в
Model, а локальное вычисленное/render state контроллера — вFeatureModelили в полях самого контроллера.
FeatureModel — компактная модель, принадлежащая одному контроллеру.
Используйте её, когда контроллеру нужно хранить собственное состояние или
выполнять фоновую задачу, а глобальная модель избыточна.
- Хранится в типобезопасном реестре контроллера.
process()выполняется каждый кадр в UI-потоке.- Избегает прямых вызовов ImGui; при необходимости обменивается событиями.
Контроллеры наследуют FeatureAccessMixin для управления моделями-фичами:
struct Counter : model::FeatureModel {
using FeatureModel::FeatureModel;
int value = 0;
void process(Pubsub::SyncNotifier&) override { ++value; }
};
class DemoController : public Controller {
public:
using Controller::Controller;
void drawContent() override {
const auto& c = feature<Counter>(
[&]{ return std::make_unique<Counter>(eventBus()); });
ImGui::Text("Frames %d", c.value);
withFeature<Counter>(
[&]{ return std::make_unique<Counter>(eventBus()); },
[](Counter& c){ if(ImGui::Button("Reset")) c.value = 0; });
}
};Для остановки фоновой работы вызовите requestClose(),
а для удаления модели — resetFeature<Counter>().
Если контроллеру нужно общее состояние приложения, предпочитайте поток DTO
через Model -> EventBus -> Controller/FeatureModel. Локальный FeatureModel
подходит для покадрово вычисляемых значений: форматированного текста, таймеров
и widget-facing view state.
graph TD
A[Application]
WM[WindowManager]
W[WindowInstance]
C[Controller]
M[Model]
EB[EventBus]
RR[ResourceRegistry]
A-->WM
A-->M
A-->EB
A-->RR
WM-->W
W-->C
C-->EB
M-->EB
C-->RR
M-->RR
sequenceDiagram
participant Model
participant EventBus
participant Controller
Model->>EventBus: notifyAsync(Event)
Note right of EventBus: queued
EventBus-->>EventBus: process()
EventBus->>Controller: notify(Event)
graph LR
core[core]
windows[windows]
controllers[controllers]
widgets[widgets]
extensions[extensions]
utils[utils]
core --> windows
core --> controllers
windows --> controllers
controllers --> widgets
controllers --> extensions
controllers --> utils
Applicationинициализирует сервисы иWindowManager.WindowManagerсоздаёт объектыWindowInstance.WindowInstance::onInit()строит контроллеры черезcreateController<T>().- Каждый кадр:
- события ввода ставятся в очередь
EventBus; EventBus::process()доставляет сообщения;WindowInstanceвызывает хуки контроллеров (drawContent,drawUi).
- события ввода ставятся в очередь
- Завершение работы выполняет хуки в обратном порядке.
Такая структура сохраняет модульность кода и простоту Immediate Mode‑рендеринга.