Виртуальный 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мотреть код простого приложения
thread_local! { pub static ROOT: Document<'static>  =  init_gui();}

call_back!(bt_click,{
    ROOT.with(|doc| {
        message("",&Text::from(doc.elem("#txtHello")).get_text())});
});	
fn main() {
    ROOT.with(|doc| {
        load(doc.elem("#divHello"),PAGE);
        Button::from(doc.elem("#btHello")).on_click(bt_click);        
    });
    loop_gui();
}

Поcмотреть код, если не нужна компиляция в asm.js
call_back!(bt_click,{
    message("",&Text::from(get_handle("#txtHello")).get_text());
});	
fn main() {
    init_gui();	
    Button::from(get_handle("#btHello")).on_click(bt_click);        
    loop_gui();
}


Комментарии

  1. Почему asm.js, а не wasm?

    ОтветитьУдалить
    Ответы
    1. Поддержка wasm в браузерах еще эксперементальная. Да и с взаимодействей с DOM есть проблемы.

      Удалить

Отправить комментарий

Популярные сообщения из этого блога

Работа с глобальными переменными в Rust

IUP - библиотека элементов GUI