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

Aug 19, 2019 19:59



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

По сравнению с исходным вариантом переделано было почти все. Пришлось перейти на подсчет ссылок и динамический borrow checker - Rc>. От рассылки и обработки сообщений отказался. Теперь архитектура такая:
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
Previous post Next post
Up