Перейти к содержанию

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 выполняет строгий конвейер по всей иерархии виджетов:

  1. measure(LayoutContext): Вычисляет желаемые размеры (desiredSize()) с учётом содержимого и ограничений контейнера.
  2. arrange(RectView): Сохраняет финальные экранные координаты и позиционирует дочерние виджеты.
  3. handle(Event): Принимает маршрутизируемые события ввода, мыши и клавиатуры.
  4. tick(FrameContext): Обновляет интерполяции, пружинные анимации и логику времени.
  5. render(RenderContext): Добавляет команды отрисовки в буфер текущего кадра.
  6. 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()

Освобождение ресурсов

Освобождает собственные ресурсы виджета перед удалением из дерева.