Widget
Базовый контракт любого элемента UI-дерева: жизненный цикл, компоновка, отрисовка, ввод и стили.
Обзор
Widget — фундаментальный интерфейс любого элемента иерархического дерева UniGUI. Он объединяет измерение размеров, размещение, визуальные стили, проверку попадания (hit testing), диспетчеризацию событий, кадровые обновления (tick) и процедурную отрисовку в единый согласованный контракт.
Интерфейс расширяет EventEmitter, благодаря чему каждый виджет дерева может подписываться на типизированные события и рассылать их.
| Подсистема | Ключевой контракт | Назначение и выполнение |
|---|---|---|
| Иерархия | parent(), children(), uiContext() |
Связи предков и потомков, координаты и контекст окна. |
| Компоновка (Layout) | measure(), arrange(), desiredSize(), layoutBounds() |
Двухпроходный layout: расчёт желаемого размера, затем фиксация границ. |
| Визуальные стили | style(), styleId(), styleClasses() |
Инлайновые CSS-декларации, токены классов и темы из StylePack. |
| Ввод и фокус | handle(), mouseCursorAt(), focusable(), focusScope() |
Обработка событий мыши, курсора и клавиатуры; скоупы фокуса. |
| Инвалидация | invalidate(), clearInvalidation(), invalidationFlags() |
Отслеживание dirty-флагов геометрии и отрисовки для исключения лишних пересчётов. |
| Рендер и тик | render(), tick(), dispose() |
Покадровые обновления, запись команд рисования и освобождение ресурсов. |
Наследование WidgetBase вместо реализации Widget
В подавляющем большинстве случаев создавайте компоненты расширением WidgetBase, а не прямой реализацией Widget. WidgetBase содержит готовую инфраструктуру: retained-кэш команд отрисовки, FLIP-анимации, вычисление стилей и всплытие инвалидации.
Жизненный цикл и конвейер
Каждый кадр среда выполнения UniGUI выполняет строгий конвейер по всей иерархии виджетов:
measure(LayoutContext): Вычисляет желаемые размеры (desiredSize()) с учётом содержимого и ограничений контейнера.arrange(RectView): Сохраняет финальные экранные координаты и позиционирует дочерние виджеты.handle(Event): Принимает маршрутизируемые события ввода, мыши и клавиатуры.tick(FrameContext): Обновляет интерполяции, пружинные анимации и логику времени.render(RenderContext): Добавляет команды отрисовки в буфер текущего кадра.dispose(): Освобождает внутренние ресурсы виджета перед его удалением из дерева.
Иерархия и структура дерева
Виджеты образуют направленное дерево под управлением методов parent() и children():
parent(): Возвращает родительский контейнер илиnull, если виджет является корнем или ещё не прикреплён к дереву.children(): Возвращает список детей в порядке обхода.- Семантика порядка: Порядок детей определяет очерёдность отрисовки (от первого к последнему: первый ребёнок снизу, последний сверху) и порядок проверки попадания hit-testing (от последнего к первому: верхний ребёнок первым принимает события мыши).
uiContext(): Предоставляет доступ к окну, диспетчеру, реестру шрифтов и сервисам ввода.
Стили и компоновка
UniGUI строго разделяет геометрию и визуальное оформление:
- Геометрия: Управляется через
layoutBounds()иdesiredSize(), настраивается вLayoutStyle. - Визуальные стили: Задаются через
styleId(...)(правило темы StylePack),styleClasses(...)(CSS-классы) или инлайновые объявления черезstyle("background: #333; radius: 8;"). - Область видимости стилей (Scope): Виджет может объявить
styleScope(true), изолируя локальные переопределения стилей от внешних деревьев.
Ввод, фокус и взаимодействие
Состояние взаимодействия управляется явными флагами:
| Флаг состояния | Назначение и эффект |
|---|---|
visibility() |
VISIBLE участвует в layout и рендере; HIDDEN сохраняет место, но скрывает визуал; COLLAPSED полностью исключается из layout. |
enabled() |
Управляет доступностью для пользователя. Отключённые виджеты игнорируют ввод и получают псевдокласс :disabled. |
hovered() |
Показывает, находится ли курсор мыши над границами виджета. |
mouseCursorAt() |
Возвращает форму курсора (например, HAND, TEXT) при наведении в локальных координатах. |
focusable() |
Определяет, может ли виджет получать фокус клавиатуры по Tab или клику. |
focusScope() |
Замыкает цикл переключения фокуса внутри поддерева (необходимо для диалогов и модальных окон). |
focusOrder() |
Явный приоритетный индекс последовательности Tab. |
Dirty-состояние и инвалидация
Для достижения максимальной частоты кадров UniGUI пропускает пересчёт компоновки и генерацию команд рендера для чистых поддеревьев:
invalidate(flags): Помечает флаги изInvalidationFlags(LAYOUT,VISUAL,RETAINED_RENDER). Флаги геометрии всплывают вверх к корню.clearInvalidation(flags): Снимает обработанные флаги после завершения прохода конвейера.subtreeInvalidationFlags(): Возвращает совокупную битовую маску dirty-флагов для виджета и всех его потомков.
Подписка на события виджета
Widget button = new Button("Отправить");
button.on(ButtonClickEvent.TYPE, event -> {
System.out.println("Нажат виджет: " + event.target().id());
});
Создание пользовательского виджета
public class CustomCard extends WidgetBase {
@Override
public void measure(LayoutContext context) {
setDesiredSize(200.0f, 100.0f);
}
@Override
public void render(RenderContext context) {
context.fillRect(layoutBounds(), 0xFF2A2A2A);
}
}
Связанные ссылки
API
Идентификация и стили
| Метод | Описание |
|---|---|
id(String) |
Назначает строковый id для поиска в дереве и отладки. |
id() |
Возвращает идентификатор виджета или пустую строку. |
styleId(String) |
Задаёт идентификатор стиля из StylePack для резолва темы. |
styleId() |
Возвращает токен стиля темы или пустую строку. |
styleClass(String) |
Задаёт классы стиля строкой через пробелы или запятые. |
styleClasses() |
Возвращает список назначенных классов стиля. |
addStyleClass(String) |
Добавляет один класс стиля к виджету. |
removeStyleClass(String) |
Удаляет один класс стиля у виджета. |
Widget::id(String)
Задать идентификатор
Назначает строковый id для поиска в дереве и отладки.
| Параметр | Тип | Описание |
|---|---|---|
id |
String |
строковый идентификатор виджета |
Возвращает Widget: этот виджет для fluent-настройки.
Widget::id()
Получить идентификатор
Возвращает идентификатор виджета или пустую строку.
Возвращает String: строка идентификатора.
Widget::styleId(String)
Задать Style ID
Задаёт идентификатор стиля из StylePack для резолва темы.
| Параметр | Тип | Описание |
|---|---|---|
styleId |
String |
токен стиля темы |
Возвращает Widget: этот виджет для fluent-настройки.
Widget::styleId()
Получить Style ID
Возвращает токен стиля темы или пустую строку.
Возвращает String: строка id стиля.
Widget::styleClass(String)
Задать классы стиля
Задаёт классы стиля строкой через пробелы или запятые.
| Параметр | Тип | Описание |
|---|---|---|
styleClasses |
String |
строка классов стиля |
Возвращает Widget: этот виджет для fluent-настройки.
Widget::styleClasses()
Получить классы стиля
Возвращает список назначенных классов стиля.
Возвращает List: список токенов классов стиля.
Widget::addStyleClass(String)
Добавить класс стиля
Добавляет один класс стиля к виджету.
| Параметр | Тип | Описание |
|---|---|---|
styleClass |
String |
добавляемый класс стиля |
Возвращает Widget: этот виджет для fluent-настройки.
Widget::removeStyleClass(String)
Удалить класс стиля
Удаляет один класс стиля у виджета.
| Параметр | Тип | Описание |
|---|---|---|
styleClass |
String |
удаляемый класс стиля |
Возвращает Widget: этот виджет для fluent-настройки.
Макет и геометрия
| Метод | Описание |
|---|---|
layoutBounds() |
Возвращает финальный прямоугольник виджета после раскладки. |
desiredSize() |
Возвращает размер, рассчитанный на последнем проходе measure. |
measure(LayoutContext) |
Измеряет виджет и рассчитывает желаемый размер для контекста. |
arrange(RectView) |
Размещает виджет в границах итогового прямоугольника. |
Widget::layoutBounds()
Границы макета
Возвращает финальный прямоугольник виджета после раскладки.
Возвращает RectView: текущие границы размещения виджета.
Widget::desiredSize()
Желаемый размер
Возвращает размер, рассчитанный на последнем проходе measure.
Возвращает LayoutSize: последний измеренный желаемый размер.
Widget::measure(LayoutContext)
Измерение
Измеряет виджет и рассчитывает желаемый размер для контекста.
| Параметр | Тип | Описание |
|---|---|---|
context |
LayoutContext |
ограничения и контекст измерения |
Widget::arrange(RectView)
Размещение
Размещает виджет в границах итогового прямоугольника.
| Параметр | Тип | Описание |
|---|---|---|
bounds |
RectView |
назначенный прямоугольник макета |
Состояние и интерактивность
| Метод | Описание |
|---|---|
visibility() |
Возвращает текущий режим видимости (VISIBLE, HIDDEN, COLLAPSED). |
visible() |
Возвращает true только при режиме VISIBLE. |
enabled() |
Возвращает true, если виджет принимает взаимодействие. |
hovered() |
Возвращает true, если указатель мыши находится над виджетом. |
focusable() |
Возвращает true, если виджет может получать клавиатурный фокус. |
Widget::visibility()
Режим видимости
Возвращает текущий режим видимости (VISIBLE, HIDDEN, COLLAPSED).
Возвращает Visibility: текущий режим видимости.
Widget::visible()
Видим ли виджет
Возвращает true только при режиме VISIBLE.
Возвращает boolean: true, если виджет в режиме VISIBLE.
Widget::enabled()
Доступен ли виджет
Возвращает true, если виджет принимает взаимодействие.
Возвращает boolean: true, если виджет включён.
Widget::hovered()
Наведён ли курсор
Возвращает true, если указатель мыши находится над виджетом.
Возвращает boolean: true, если курсор над виджетом.
Widget::focusable()
Фокусируемость
Возвращает true, если виджет может получать клавиатурный фокус.
Возвращает boolean: true, если виджет фокусируемый.
Отрисовка и кэширование
| Метод | Описание |
|---|---|
render(RenderContext) |
Отрисовывает виджет в текущем контексте кадра. |
Widget::render(RenderContext)
Отрисовка
Отрисовывает виджет в текущем контексте кадра.
| Параметр | Тип | Описание |
|---|---|---|
context |
RenderContext |
контекст отрисовки кадра |
События и жизненный цикл
| Метод | Описание |
|---|---|
uiContext() |
Возвращает runtime-контекст с сервисами dispatcher, theme и input. |
parent() |
Возвращает родительский виджет в дереве UI. |
children() |
Возвращает дочерние элементы в порядке обхода/раскладки. |
invalidationFlags() |
Возвращает битовую маску текущих флагов инвалидации. |
invalidate(int) |
Выставляет флаги инвалидации (VISUAL, LAYOUT, HIERARCHY и др.). |
clearInvalidation(int) |
Снимает обработанные флаги инвалидации. |
handle(Event) |
Обрабатывает маршрутизированное или прямое событие UI. |
tick(FrameContext) |
Обновляет покадровое состояние, таймеры и анимации. |
dispose() |
Освобождает собственные ресурсы виджета перед удалением из дерева. |
Widget::uiContext()
UI Context
Возвращает runtime-контекст с сервисами dispatcher, theme и input.
Возвращает UIContext: активный UIContext или null, если виджет отсоединён.
Widget::parent()
Родительский виджет
Возвращает родительский виджет в дереве UI.
Возвращает Widget: родительский виджет или null для корня.
Widget::children()
Дочерние виджеты
Возвращает дочерние элементы в порядке обхода/раскладки.
Возвращает List: список дочерних элементов.
Widget::invalidationFlags()
Флаги инвалидации
Возвращает битовую маску текущих флагов инвалидации.
Возвращает int: битовая маска dirty-флагов.
Widget::invalidate(int)
Инвалидировать
Выставляет флаги инвалидации (VISUAL, LAYOUT, HIERARCHY и др.).
| Параметр | Тип | Описание |
|---|---|---|
flags |
int |
битовая маска из InvalidationFlags |
Widget::clearInvalidation(int)
Снять флаги инвалидации
Снимает обработанные флаги инвалидации.
| Параметр | Тип | Описание |
|---|---|---|
flags |
int |
битовая маска обработанных флагов |
Widget::handle(Event)
Обработка события
Обрабатывает маршрутизированное или прямое событие UI.
| Параметр | Тип | Описание |
|---|---|---|
event |
Event |
объект события |
Widget::tick(FrameContext)
Тик кадра
Обновляет покадровое состояние, таймеры и анимации.
| Параметр | Тип | Описание |
|---|---|---|
frame |
FrameContext |
контекст текущего кадра |
Widget::dispose()
Освобождение ресурсов
Освобождает собственные ресурсы виджета перед удалением из дерева.