Виртуальный GUI на Rust
Рассмотрим создание приложений с графическим интерфейсом, который бы работал на рабочем столе и в браузере без изменения кода. В качестве крос-платформенной библиотеки для приложений для рабочего стола будем использовать библиотеку IUP , для работы в браузере , естественно , DOM.
Конечно нам понадобятся библиотеки-фасады, которые инкапсулируют разницу между этими библиотеками. Для этого я написал библиотеки RIUP и RDOM.
Необходимо отметить ,что идеологично IUP сильно похожа на DOM , в отличии от других графических библиотек для рабочого стола. На нижнем уровне этих библиотек находятся Ihandle для IUP и HtmlNode для DOM - поведение и внешний вид которых зависит от их атрибутов. RIUP и RDOM обладают функциями нижнего уровня для работы с атрибутами и структурами с набором функций для конкретных виджетов. Эти виджеты -обёртки над Ihandle и HtmlNode.
К основным функциям нижнего уровня относятся:
get_attr_str(w: *Ihandle/ &HtmlNode, attr: &str)->String;
get_attr_int(w: *Ihandle/ &HtmlNode, attr: &str)->i32;
set_attr_str(w: *Ihandle/ &HtmlNode, attr: &str, v: &str);
set_attr_int(w: *Ihandle/ &HtmlNode, attr: &str, v: i32);
Если у нас есть кнопка bt то set_attr_str(bt, “TITLE”,”hello”) изменит надпись на ней на “hello” при работе с RIUP, но при работе с RDOM необходим другой атрибут set_attr_str(bt, “value”,”hello”)
На высоком уровне это будет так : bt.set_text(“hello”) , но для этого bt уже не Ihandle или HtmlNode, а Button.
Функции и виджеты нижнего уровня используются в основном для обработки структур данных в которых виджет это поле, которое может содержать разные виджеты.
[Card::new(txtName,TEXT,...),Card::new(cbCat,INDEX,...)...]
Это может быть альтернативой упаковки виджетов высокого уровня в АTD (алгебраичные типы данных)
Одинаковость имён и функций виджетов высокого уровня в RIUP и RDOM - это ещё не решение всех проблем. Есть отличия регистрации их в системе и разный формат callback функций.
В DOM каждый виджет должен иметь свой уникальный id в границах документа. IUP допускает два варианта: уникальный id в границах приложения или уникальное имя в границах отдельного окна. Учитывая это, а также то, что при работе в браузере наши окна это на самом деле DIV, необходимо будет давать виджетам уникальные имена в границах приложения.
Поиск виджета в системе по имени происходит с помошью функции elem(name: &str) Эта функция структуры Document.
Эта структура введена в RIUP исключительно для совместимости с RDOM. Если совместимость не нужна , то в RIUP сть функция get_handle(name: &str) не привязанная ни к одной структуре.
Создать виджет высокого уровня из существующего *Ihandle/ &HtmlNode можно с помощью функции
from(w:*Ihandle/ &HtmlNode) - она есть в каждом виджете высокого уровня.
В IUP callback функция имеет формат:
extern fn name(w: IUPPtr, p1 :CBPtr, p2: CBPtr, p3: CBPtr)->i32
а в DOM fn name(w: Event)
Изменять заголовки всех callback функций и тип результата перед перекомпиляцией под другую платформу - плохая идея. Но Rust имеет достаточно неплохую систему макросов, как для негомоиконного языка программирования.
Макрос callback! (название ф-и, { код реализации}) решит наши проблемы))
Поcмотреть код простого приложения
Поcмотреть код, если не нужна компиляция в asm.js
Почему asm.js, а не wasm?
ОтветитьУдалитьПоддержка wasm в браузерах еще эксперементальная. Да и с взаимодействей с DOM есть проблемы.
Удалить