Михаил Ильин (yorool_gui) wrote,
Михаил Ильин
yorool_gui

GUI на Rust - есть прогресс

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

По сравнению с исходным вариантом переделано было почти все. Пришлось перейти на подсчет ссылок и динамический borrow checker — Rc<RefMut<Объект>>. От рассылки и обработки сообщений отказался. Теперь архитектура такая:
1. Виджеты собраны в дерево. Сообщения от ggez (нажатия кнопок, резайз окна, запрос на отрисовку и т.д.) пересылаются вниз по дереву.
2. Виждеты могут иметь обработчики событий. Обработчики вызываются не в момент обхода дерева (тогда бы были проблемы с borrow checker), а собираются в массив и вызываются после
3. Виджеты могут реализовывать интерфейсы. Например Checkbox реализует ICheckbox с методами get_state/set_state. А RadioGroup позволяет объединить в группу радиокнопок любые объекты, которые предоставляют ICheckbox. Аналогично будут сделаны методы типа enable/disable,  set_text/get_text и т.д.

Код выглядит вот так. borrow_mut() и clone() в глазах рябят конечно, но привыкнуть можно.


        let radio_a = CheckboxBuilder::new().build();
        let radio_b = CheckboxBuilder::new().build();
        let radio_c = CheckboxBuilder::new().build();

        let radio_group = RadioGroupBuilder::new()
            .add_widget(radio_a.clone())
            .add_widget(radio_b.clone())
            .add_widget(radio_c.clone())
            .build();

        let radio_ribbon = RibbonBuilder::new()
            .set_horizontal(true)
            .add_widget(radio_a)
            .add_widget(radio_b)
            .add_widget(radio_c)
            .build();

        let add_radio = {
            let radio_group = radio_group.clone();
            let radio_ribbon = radio_ribbon.clone();
            move |_| {
                let radio = CheckboxBuilder::new().build();
                radio_group.borrow_mut().add_widget(radio.clone());
                radio_ribbon.borrow_mut().add_widget(radio.clone());
            }
        };

        let remove_radio = {
            let radio_group = radio_group.clone();
            let radio_ribbon = radio_ribbon.clone();
            move |_| {
                let radio = radio_group.borrow().radios().last().map(|r| r.clone());
                if let Some(radio) = radio {
                    radio_group.borrow_mut().remove_widget(radio.clone());
                    radio_ribbon.borrow_mut().remove_widget(radio.clone());
                }
            }
        };

        let panel = PanelBuilder::new()
            .add_widget(
                RibbonBuilder::new()
                    .set_horizontal(false)
                    .add_widget(radio_ribbon.clone())
                    .add_widget(
                        RibbonBuilder::new()
                            .set_horizontal(true)
                            .add_widget(ButtonBuilder::new().on_click(add_radio).build())
                            .add_widget(ButtonBuilder::new().on_click(remove_radio).build())
                            .build(),
                    )
                    .build(),
            )
            .build();

        wm.add_window(panel, Rect::zero(), true);


Репозиторий - https://github.com/milyin/yorool_gui
Subscribe

  • Post a new comment

    Error

    Anonymous comments are disabled in this journal

    default userpic

    Your reply will be screened

    Your IP address will be recorded 

  • 0 comments