Indyvon — многопоточная библиотека графического интерфейса
пользователя, написанная на языке Clojure.

Особенности:
 - базовый элемент интерфейса (сцены) не имеет состояния;
 - параллельная отрисовка;
 - нет статической сцены: расположение элементов фиксируется для
   обработки событий при каждой перерисовке и используется до
   завершения отрисовки следующего кадра;
 - преобразования элементов с помощью AffineTransform;
 - произвольная область отсечения (форма элементов), которая
   учитывается при обработке событий.

Базовый элемент пользовательского интерфейса описан протоколом Layer
(слой), который содержит всего две функции:

  render! — отрисовка,
  geometry — получение предпочтительных размеров элемента.

Слой, в отличии от обычных компонентов интерфейса или элементов графов
сцены в системах визуализации, не имеет состояния (координаты, размер,
элемент-родитель, дочерние элементы) и может быть изображен по-разному
на каждой итерации цикла отрисовки.

Функции слоя выполняются в контексте слоя (layer context), который
представлен набором связанных переменных, в том числе:

  *graphics* — экземпляр java.awt.Graphics2D для рисования,
  *width* и *height* — размеры области рисования,
  *clip* — область отсечения (произвольная, java.awt.geom.Shape),
  *event-dispatcher* — диспетчер событий.

Во время отрисовки можно устанавливать обработчики событий ввода
(сейчас поддерживаются только события мыши) для текущего
контекста. При установке обработчика контекст сохраняется для
обработки событий до завершения следующей перерисовки сцены.

Слои могут инициировать перерисовку с помощью механизма
уведомлений. Обработчики уведомлений, как и обработчики событий,
устанавливаются на время до следующей перерисовки.

Таким образом, получать события ввода и вызывать перерисовку могут
только те слои, которые в данный момент видны на экране, т. е.
участвовали в последней перерисовке.

Сцена может строиться во время выполнения отрисовки (как в IMGUI:
"сейчас нарисовать здесь кнопку") или описываться путем композиции
слоев (предполагая, что реализованы функции border, vbox, label и
button, которые создают слои):

  (border
    (hbox
      (label "Comment:") 
      (button (label "Button"))))

Отрисовку можно распараллелить с помощью функции async-layer, которая
возвращает слой, показывающий результат отрисовки слоя-аргумента. При
этом отрисовка слоя-аргумента выполняется в параллельной нити в буфер
в памяти. Для избежания блокировок используется тройная
буферизация. Слои, помещенные в async-layer, не будут ограничивать
частоту кадров и могут обновляться медленнее, чем основная сцена.