LINUX.ORG.RU

Universal UI for Rust

 , , ,


4

4

Доброго времени суток.

Примерно полгода назад, когда я начинал изучать Rust, я обнаружил в нем фатальный недостаток - отсутсвие крейта, который бы реализовывал удобный и кроссплатформенный UI. Хотелось поддержки Linux/Windows/MacOS/WASM-web/Android/iOS и удобства использования уровня Qt с их сигналами-слотами.

В ходе парочки бессоных ночей (на самом деле намного больше) появилась некоторое количество крейтов, которые позволяет писать UI вот так:

#[derive(UWidget)]
struct MyWidget {
    #[uwidget]
    layout: LinearLayout,

    #[public_slot] // у структуры будет публичный метод, через который слот будет доступен снаружи
    #[uprocess(on_text_updated)]
    slot_set_text: SlotImpl<String>,

    slotproxy_set_text: SlotProxy<String>,

    #[uprocess(on_button_clicked)]
    slot_button_clicked: SlotImpl<()>,
}

impl MyWidget {
    pub fn new(placeholder: String) -> MyWidget {
        let slotproxy_set_text;
        let slot_button_clicked = SlotImpl::new();

        let mut layout = LinearLayout::new(Orientation::Horizontal);
        layout.push_widget({
           let textedit = TextEdit::new(placeholder);
           slotproxy_set_text = textedit.slot_set_text().proxy();
           textedit
        });

        layout.push_widget({
            let mut button  = Button::new("Push me");
            button.signal_clicked().connect(&slot_button_clicked);
            button
        });

        return MyWidget{
            layout,
            slot_set_text: SlotImpl::new(),
            slotproxy_set_text,
            slot_button_clicked,
        };
    }

    fn on_text_updated(&self, s: String) {
        self.slotproxy_set_text.exec_for(s);
    }

    fn on_button_clicked(&self, _:()) {
        info!("button clicked!");
    }
}



В ближайшем будущем планирую еще немного посидеть над макросами, чтобы можно было писать вот так:

pub fn new(placeholder: String) -> MyWidget {
    let layout = layout!(
        orientation: Horizontal,
        widget: text_edit!(
        	placeholder: placeholder,
        	slot_set_text: proxy!(slotproxy_set_text),
        ),
        widget: button!(
        	signal_clicked: connect!(slot_button_clicked),
        ),
    );

    return MyWidget{
        layout,
        slot_set_text: SlotImpl::new(),
        slotproxy_set_text,
        slot_button_clicked,
    };
}


Немного технических подробностей:
* Уже работает для Linux (Qt) и WASM (web-sys).
** В ближайших планах минимальная поддержка Windows/MacOS через Qt и поддержка Android (Java-jni, нативные виджеты).
** В среднесрочных планах поддержка нативных виджетов Win/Mac, поддержка iOS.
* Система сборки на build.rs-скриптах для cargo, которая позволяет из одних и тех же исходников собирать проект для любой платформы. Небольшой (2-5 строк) скрипт придется написать самому, используя готовые функции из библиотеки.
* В самой библиотеке есть еще Property, которые умеют хранить состояние и обладают встроенными сигналами/слотами. И немного других улучшалок.
* Никаких unsafe в интерфейсах для пользователя (внутри - только для работы с native-кодом).
* Никаких RefCell, Rc и прочих Arc в интерфейсах. Внутри их тоже практически нет, к релизу хочу выпилить совсем.


В основном вдохновлялся Qt, но изначально все писалось под web-sys, с последующим прикручиванием Desktop'а.


Тут хотелось бы обсудить 2 вещи (на самом деле 3):
1. Интересна ли вам такая библиотека.
2. Насколько удобным выглядит интерфейс.
3. Насколько Rust ущербен, порекомендуйте уже готовые библиотеки, и вот это вот все.

P.S. Буду держать вас в курсе, так что можете сразу ставить uniui тег в игнор.

★★★★★

Добро пожаловать в число тех, кто пилит очередной GUI фреймворк на расте. Таких как ты много.

Перед тем, как ты начнёшь рассказывать, чем твое решение принципиально лучше, спрошу: у тебя там можно руками рисовать кастомные виджеты, или всё как обычно у писак фреймворков?

quantum-troll ★★★★★ ()
Ответ на: комментарий от quantum-troll

у тебя там можно руками рисовать кастомные виджеты

Есть поддержка canvas и opengl/webgl.

Каждый виджет лежит в отдельном крейте, чтобы не быть связаным c внутренностями core-части.

trex6 ★★★★★ ()
Последнее исправление: trex6 (всего исправлений: 2)

Пристально слежу за темой, но воз и ныне там. Проще всего писать на Qt, а Rust дергать через json-rpc. Все текущие реализации гуи - просто унылый ужас.

RazrFalcon ★★★★★ ()

Пока кто-нибудь не долбанется настолько, что бы написать гимп, ворд или компас на расте, гуе-фреймворка мы не получим. Поделки на то и поделки, что реальное применение в них не продумано

zendrz ()

Примерно полгода назад, когда я начинал изучать Rust, я обнаружил в нем фатальный недостаток - отсутсвие крейта, который бы реализовывал удобный и кроссплатформенный UI.

Это не недостаток не Rust, ни какого-либо иного языка программирования.

Владимир

anonymous ()

Метапрог всех «заткнет за пояс» /у него обширные планы/.
Разработчики QT, GTK, … еще не догадываются, что скоро им придет - …

«Гусарам молчать!» /мой вариант «капут»/.

Владимир

anonymous ()

GUI надо отделять от ядра приложения, это многие пишут. Только отделять можно и на другом ЯП с нормальными тулкитами, типа питона, QML, да хоть HTML/CSS/JS в браузере, как делает CUPS.

ArkaDOSik ★★ ()
Ответ на: комментарий от RazrFalcon

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

WatchCat ★★★★★ ()
Последнее исправление: WatchCat (всего исправлений: 1)

Сам не знаю для чего, но решил изучить и попробовать rust для своих gui поделок, которые сейчас на qt

Но отсутствие аналога qt меня и остановило, а может мне оно и не надо

x905 ★★★★★ ()
Последнее исправление: x905 (всего исправлений: 1)
Ответ на: комментарий от RazrFalcon

Все текущие реализации гуи - просто унылый ужас.

Было бы интересно почитать о том, что именно вас не устраивает в других реализациях. Вдруг, моя реализация лишина и этих фатальных недостатоков.

trex6 ★★★★★ ()
Ответ на: комментарий от zendrz

Насколько я помню, автор druid использует его для редактора шрифтов. Возможно и другие библиотеки так же создаются не на ровном месте.

Я свою начал писать для визуализации игры.

trex6 ★★★★★ ()
Ответ на: комментарий от WatchCat

Благо делается это там достаточно легко.

До тех пор, пока вам не нужно пересылать что-то сложнее int/float. Даже со строками начинаются «пляски», а со сложными/древовидными структурами данных - совсем все плохо. Плюс придется обмазываться unsafe по всему коду.

Как результат, для конкретной билиотеки, обычно, пишут отдельную обвязку, чтобы весь «секс» локализировать в одном крейте. Ну а крейт этот потом уезжает на crates.io.

trex6 ★★★★★ ()
Ответ на: комментарий от fsb4000

И еще десяток других есть. Но мне интерфейсы нигде не понравились.

Хочу чтобы все было так же просто, как Qt с их сигналами-слотами. Пропихивать повсюду лямбды/FnMut-ы - не мое.

trex6 ★★★★★ ()
Ответ на: комментарий от trex6

а со сложными/древовидными структурами данных - совсем все плохо.

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

А если у тебя всё так сложно и ты в ui передаёшь что-то выходящее из этих рамок, то КМК тут проблемы в изначальном проектировании.

WatchCat ★★★★★ ()

#[public_slot] // у структуры будет публичный метод, через который слот будет доступен снаружи

Очевидно, что никаких методов особенно публичных у тебя нет.

let slot_button_clicked = SlotImpl::new(); connect(&slot_button_clicked)

Очевидно, что это не сработает.

  • Никаких unsafe в интерфейсах для пользователя (внутри - только для работы с native-кодом).

Зачем ты врёшь?

Но ты пили, потом покажешь.

anonymous ()
Ответ на: комментарий от trex6

Так оно уже работает.

Оно не может работать в таком виде. Ты не можешь реализовать коннекты не через unsafe и не может их реализовать через ссылки.

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

anonymous ()

Небольшой отчет о том, как идут дела:

* Постепенно начинаю публиковать крейты на crates.io. Очень много времени занимает написание документации. Основаная сложность - описать все основные концепции достаточно кратко. Хотелось бы, чтобы начать пользоваться этим пепелацем можно было в течении нескольких минут.

* Сама концепция платформы немного расширилась. Теперь она не ограничивается UI приложениями, а позволяет писать гетерогенные приложения, состоящие из бекенда, Web(WASM), Android, iOS, Linux, Mac, Windows. Основной упор все еще сделан на UI части.

* Для WASM уже готова куча виджетов. В целом удается писать небольшие приложения (5-10 экранов с бизнес-логикой) на чистом Rust без использования JS и web-sys/js-sys за пределами библиотек.

* Работы по портированию на Qt заморожены. Причиной послужили последние изменения в лицензионной политике разработчиков. Пока непонятно, есть ли смысл продолжать развивать Qt-порт или лучше переключится на что-то другое (но что? GTK?).

* Порт на Андроид работает, все технические вопросы решены. Пока еще не реализованна поддержка всех виджетов. Впереди много монотонной работы.

* Порт на iOS в разработке. Такое ощущение, что все технические сложности уже преодолены и осталось только собрать все в один билдскрипты. Хочу завершить эти работы в ближайшие недели.

* Порт на MacOS. Думаю отказаться от отдельного порта и вместо этого использовать MacOS'Catalyst, это должно позволить использовать общие виджеты с iOS портом. Поддержка Catalyst в Rust сейчас находится на начальном этапе (в ходе короткой попытки мне так и не удалось заставить xargo собрать стандартную библиотеку). Попробую посмотреть, поменяется ли что-то к новому году.

* Порт на Windows. Тут все совсем плохо. Работы даже не начинались, а начать их нужно с покупки ноута/компа с работающей Win10.


Постараюсь снова выйти на связь ближе к новому году.

Всем хорошего дня!



P.S. Если кто-то хотел бы поучаствовать в проекте - пишите в этой теме. Я буду благодарен любой помощи! Мне кажется, что особенно полезным было бы:
* перечитать документацию, проверить ошибки, попробовать пройти все шаги из tutorial на «чистой» системе и посмотреть, какие ошибки могут возникнуть у потенциальных пользователей,
* попробовать собрать небольшие приложения (сапер, змейка и т.п.),
* помощь по портированию уже готовых виджетов на Андроид,
* помощь с разработкой Windows-порта.

trex6 ★★★★★ ()