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

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

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

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

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

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

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

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

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

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

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

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

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