Attempt 3 to make mutability-independent UI
This commit is contained in:
parent
09b732cfbc
commit
2ea5448ae3
36
utility/src/gat_iterator.rs
Normal file
36
utility/src/gat_iterator.rs
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
pub trait GatIterator {
|
||||||
|
type Item<'x>
|
||||||
|
where
|
||||||
|
Self: 'x;
|
||||||
|
|
||||||
|
fn next<'s>(&'s mut self) -> Option<Self::Item<'s>>;
|
||||||
|
|
||||||
|
fn forEach(mut self, mut consumer: impl for<'x> FnMut(Self::Item<'x>))
|
||||||
|
where
|
||||||
|
Self: Sized,
|
||||||
|
{
|
||||||
|
loop {
|
||||||
|
match self.next() {
|
||||||
|
None => return,
|
||||||
|
Some(i) => consumer(i)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*pub fn make_lambda<'z, I: Iterator>(it: I) -> impl for<'x> LambdaIterator<Item<'x> = I::Item> {
|
||||||
|
return LambdaIteratorConverter { it };
|
||||||
|
}
|
||||||
|
|
||||||
|
struct LambdaIteratorConverter<I: Iterator> {
|
||||||
|
it: I,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<I: Iterator> LambdaIterator for LambdaIteratorConverter<I> {
|
||||||
|
type Item<'x> = I::Item where Self:'x;
|
||||||
|
|
||||||
|
fn next<'s, R>(&mut self, receiver: impl for<'x> FnOnce(I::Item) -> R) -> Option<R> {
|
||||||
|
return self.it.next().map(receiver);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
@ -93,6 +93,13 @@ impl<T> _PreserveIndexVec<T> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn iter_indexes(&self) -> impl Iterator<Item = (usize)> {
|
||||||
|
return self.buffer.iter().enumerate().filter_map(|(i, c)| match c {
|
||||||
|
Cell::Free { .. } => return None,
|
||||||
|
Cell::Value { value } => return Some(i),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
pub fn capacity(&self) -> usize {
|
pub fn capacity(&self) -> usize {
|
||||||
return self.buffer.len();
|
return self.buffer.len();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,8 @@
|
|||||||
use super::{_ConstMutSwitchUiCallback, ConstMutSwitchUi, ConstRef, RefType, _ConstMutSwitchUiTableHeaderCallback};
|
use super::{
|
||||||
|
_ConstMutSwitchUiCallback, _ConstMutSwitchUiTableHeaderCallback,
|
||||||
|
_ConstMutSwitchUiTableCallback, ConstMutSwitchUi, ConstRef, MutRef, MutUI, RefType,
|
||||||
|
};
|
||||||
|
use crate::gui::const_mut_switch::table::ConstMutSwitchUiTableImplState;
|
||||||
use eframe::egui::{ScrollArea, Ui};
|
use eframe::egui::{ScrollArea, Ui};
|
||||||
use eframe::emath::Numeric;
|
use eframe::emath::Numeric;
|
||||||
use std::ops::RangeInclusive;
|
use std::ops::RangeInclusive;
|
||||||
@ -61,22 +65,22 @@ impl ConstMutSwitchUi for ConstUI<'_> {
|
|||||||
self.ui.separator();
|
self.ui.separator();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn scroll_area_2(
|
fn scroll_area_2(&mut self, scope: impl _ConstMutSwitchUiCallback<Self::RefType>) {
|
||||||
&mut self,
|
|
||||||
scope: impl _ConstMutSwitchUiCallback<Self::RefType>,
|
|
||||||
) {
|
|
||||||
ScrollArea::both()
|
ScrollArea::both()
|
||||||
.auto_shrink([false, false])
|
.auto_shrink([false, false])
|
||||||
.show_viewport(self.ui, |ui, _| scope.render(&mut ConstUI { ui }));
|
.show_viewport(self.ui, |ui, _| scope.render(&mut ConstUI { ui }));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fn table(
|
fn table(
|
||||||
&mut self,
|
&mut self,
|
||||||
vscroll: bool,
|
vscroll: bool,
|
||||||
columns: usize,
|
columns: usize,
|
||||||
header: impl _ConstMutSwitchUiTableHeaderCallback<Self::RefType>,
|
scope: impl _ConstMutSwitchUiTableCallback<Self::RefType>,
|
||||||
) {
|
) {
|
||||||
super::render_table::<ConstRef, Self>(self.ui, vscroll, columns, header);
|
scope.render_table(
|
||||||
|
&mut ConstMutSwitchUiTableImplState::<ConstRef, ConstUI>::new(
|
||||||
|
self.ui, vscroll, columns,
|
||||||
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,8 +7,10 @@ mod r#trait;
|
|||||||
pub use r#const::ConstUI;
|
pub use r#const::ConstUI;
|
||||||
pub use r#mut::MutUI;
|
pub use r#mut::MutUI;
|
||||||
pub use r#ref::{ConstRef, MutRef, RefType};
|
pub use r#ref::{ConstRef, MutRef, RefType};
|
||||||
use table::render_table;
|
use table::ConstMutSwitchUiTableImplState;
|
||||||
pub use table::{
|
pub use table::{
|
||||||
_ConstMutSwitchUiTableHeaderCallback, _ConstMutSwitchUiTableRowCallback, ConstMutSwitchUiTableRow,
|
_ConstMutSwitchUiTableCallback, _ConstMutSwitchUiTableHeaderCallback,
|
||||||
|
_ConstMutSwitchUiTableRowCallback, _ConstMutSwitchUiTableRowsIterator, ConstMutSwitchUiTable,
|
||||||
|
ConstMutSwitchUiTableRow,
|
||||||
};
|
};
|
||||||
pub use r#trait::{_ConstMutSwitchUiCallback, ConstMutSwitchUi};
|
pub use r#trait::{_ConstMutSwitchUiCallback, ConstMutSwitchUi};
|
||||||
|
|||||||
@ -1,4 +1,8 @@
|
|||||||
use super::{_ConstMutSwitchUiTableHeaderCallback, ConstMutSwitchUi, MutRef, RefType};
|
use super::{
|
||||||
|
_ConstMutSwitchUiTableHeaderCallback, _ConstMutSwitchUiTableCallback, ConstMutSwitchUi,
|
||||||
|
MutRef, RefType,
|
||||||
|
};
|
||||||
|
use crate::gui::const_mut_switch::table::ConstMutSwitchUiTableImplState;
|
||||||
use crate::gui::const_mut_switch::r#trait::_ConstMutSwitchUiCallback;
|
use crate::gui::const_mut_switch::r#trait::_ConstMutSwitchUiCallback;
|
||||||
use eframe::egui::{ScrollArea, Ui};
|
use eframe::egui::{ScrollArea, Ui};
|
||||||
use eframe::emath::Numeric;
|
use eframe::emath::Numeric;
|
||||||
@ -68,8 +72,10 @@ impl ConstMutSwitchUi for MutUI<'_> {
|
|||||||
&mut self,
|
&mut self,
|
||||||
vscroll: bool,
|
vscroll: bool,
|
||||||
columns: usize,
|
columns: usize,
|
||||||
header: impl _ConstMutSwitchUiTableHeaderCallback<Self::RefType>,
|
scope: impl _ConstMutSwitchUiTableCallback<Self::RefType>,
|
||||||
) {
|
) {
|
||||||
super::render_table::<MutRef, Self>(self.ui, vscroll, columns, header);
|
scope.render_table(&mut ConstMutSwitchUiTableImplState::<MutRef, MutUI>::new(
|
||||||
|
self.ui, vscroll, columns,
|
||||||
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,20 +3,32 @@
|
|||||||
use super::{
|
use super::{
|
||||||
_ConstMutSwitchUiCallback, ConstMutSwitchUi, ConstRef, ConstUI, MutRef, MutUI, RefType,
|
_ConstMutSwitchUiCallback, ConstMutSwitchUi, ConstRef, ConstUI, MutRef, MutUI, RefType,
|
||||||
};
|
};
|
||||||
use crate::LambdaIterator;
|
use crate::{GatIterator, LambdaIterator};
|
||||||
use eframe::egui::Ui;
|
use eframe::egui::Ui;
|
||||||
use egui_extras::{Column, TableBuilder, TableRow};
|
use egui_extras::{Column, Table, TableBuilder, TableRow};
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
use std::mem::uninitialized;
|
use std::mem::{swap, uninitialized};
|
||||||
|
|
||||||
|
pub trait _ConstMutSwitchUiTableCallback<RefType: super::RefType> {
|
||||||
|
fn render_table(self, ctx: &mut impl ConstMutSwitchUiTable<RefType = RefType>);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait ConstMutSwitchUiTable {
|
||||||
|
type RefType: super::RefType;
|
||||||
|
fn header(&mut self, scope: impl _ConstMutSwitchUiTableHeaderCallback<Self::RefType>);
|
||||||
|
fn body(&mut self, scope: impl _ConstMutSwitchUiTableRowsIterator<Self::RefType>);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait _ConstMutSwitchUiTableRowsIterator<RefType: super::RefType> {
|
||||||
|
type Item<'x>: _ConstMutSwitchUiTableRowCallback<RefType>
|
||||||
|
where
|
||||||
|
Self: 'x;
|
||||||
|
|
||||||
|
fn next<'s>(&'s mut self) -> Option<Self::Item<'s>>;
|
||||||
|
}
|
||||||
|
|
||||||
pub trait _ConstMutSwitchUiTableHeaderCallback<RefType: super::RefType> {
|
pub trait _ConstMutSwitchUiTableHeaderCallback<RefType: super::RefType> {
|
||||||
type RowRender: _ConstMutSwitchUiTableRowCallback<RefType>;
|
fn render_header(self, ctx: &mut impl ConstMutSwitchUiTableRow<RefType = RefType>);
|
||||||
type RowsIterator: LambdaIterator<Item = Self::RowRender>;
|
|
||||||
|
|
||||||
fn render_header(
|
|
||||||
self,
|
|
||||||
ctx: &mut impl ConstMutSwitchUiTableRow<RefType = RefType>,
|
|
||||||
) -> Self::RowsIterator;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait _ConstMutSwitchUiTableRowCallback<RefType: super::RefType> {
|
pub trait _ConstMutSwitchUiTableRowCallback<RefType: super::RefType> {
|
||||||
@ -70,36 +82,90 @@ impl __SwitchUiConstructor1<MutRef> for MutUI<'_> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn render_table<
|
pub(super) enum ConstMutSwitchUiTableImplState<
|
||||||
RefType: super::RefType,
|
'a,
|
||||||
Constructor: __SwitchUiConstructor1<RefType>,
|
RT: RefType,
|
||||||
>(
|
Constructor: __SwitchUiConstructor1<RT>,
|
||||||
ui: &mut Ui,
|
> {
|
||||||
vscroll: bool,
|
Header(TableBuilder<'a>),
|
||||||
columnsCount: usize,
|
Body(Table<'a>),
|
||||||
header_render: impl _ConstMutSwitchUiTableHeaderCallback<RefType>,
|
Done(PhantomData<(RT, Constructor)>),
|
||||||
) {
|
}
|
||||||
let mut rows_it = unsafe { uninitialized() };
|
|
||||||
|
impl<'a, RT: RefType, Constructor: __SwitchUiConstructor1<RT>>
|
||||||
|
ConstMutSwitchUiTableImplState<'a, RT, Constructor>
|
||||||
|
{
|
||||||
|
pub fn new(ui: &'a mut Ui, vscroll: bool, columns_count: usize) -> Self {
|
||||||
|
return Self::Header(
|
||||||
TableBuilder::new(ui)
|
TableBuilder::new(ui)
|
||||||
.striped(true) // Alternating row colors
|
.striped(true) // Alternating row colors
|
||||||
.resizable(true)
|
.resizable(true)
|
||||||
.vscroll(vscroll)
|
.vscroll(vscroll)
|
||||||
.columns(Column::remainder(), columnsCount)
|
.columns(Column::remainder(), columns_count),
|
||||||
.header(20.0, |row| {
|
);
|
||||||
rows_it =
|
}
|
||||||
header_render.render_header(&mut ConstMutSwitchUiTableRowImpl::<_, Constructor> {
|
|
||||||
row,
|
#[allow(deprecated)]
|
||||||
__phantom: PhantomData::default(),
|
fn header_map(&mut self, f: impl FnOnce(TableBuilder) -> Table) {
|
||||||
});
|
match self {
|
||||||
})
|
ConstMutSwitchUiTableImplState::Header(_) => {
|
||||||
.body(|mut body| {
|
let mut local = unsafe { Self::Header(uninitialized()) };
|
||||||
rows_it.consume(|row_render| {
|
swap(self, &mut local);
|
||||||
body.row(20.0, |row| {
|
if let Self::Header(local) = local {
|
||||||
row_render.render_row(&mut ConstMutSwitchUiTableRowImpl::<_, Constructor> {
|
*self = Self::Body(f(local))
|
||||||
row,
|
}
|
||||||
__phantom: PhantomData::default(),
|
}
|
||||||
})
|
_ => panic!("Not in header state"),
|
||||||
})
|
}
|
||||||
});
|
}
|
||||||
});
|
|
||||||
|
#[allow(deprecated)]
|
||||||
|
fn body_map(&mut self, f: impl FnOnce(Table)) {
|
||||||
|
match self {
|
||||||
|
ConstMutSwitchUiTableImplState::Header(_) => {
|
||||||
|
let mut local = unsafe { Self::Body(uninitialized()) };
|
||||||
|
swap(self, &mut local);
|
||||||
|
if let Self::Body(local) = local {
|
||||||
|
f(local);
|
||||||
|
*self = Self::Done(PhantomData::default())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => panic!("Not in body state"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<RT: RefType, Constructor: __SwitchUiConstructor1<RT>> ConstMutSwitchUiTable
|
||||||
|
for ConstMutSwitchUiTableImplState<'_, RT, Constructor>
|
||||||
|
{
|
||||||
|
type RefType = RT;
|
||||||
|
|
||||||
|
fn header(&mut self, scope: impl _ConstMutSwitchUiTableHeaderCallback<Self::RefType>) {
|
||||||
|
self.header_map(|h| {
|
||||||
|
return h.header(20.0, |row| {
|
||||||
|
scope.render_header(&mut ConstMutSwitchUiTableRowImpl::<_, Constructor> {
|
||||||
|
row,
|
||||||
|
__phantom: PhantomData::default(),
|
||||||
|
})
|
||||||
|
});
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn body(&mut self, mut scope: impl _ConstMutSwitchUiTableRowsIterator<Self::RefType>) {
|
||||||
|
self.body_map(|body| {
|
||||||
|
body.body(|mut b| {
|
||||||
|
loop {
|
||||||
|
match scope.next() {
|
||||||
|
None => break,
|
||||||
|
Some(rs) => b.row(20.0, |rn| {
|
||||||
|
rs.render_row(&mut ConstMutSwitchUiTableRowImpl::<_, Constructor> {
|
||||||
|
row: rn,
|
||||||
|
__phantom: PhantomData::default(),
|
||||||
|
})
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
use super::{_ConstMutSwitchUiTableHeaderCallback, RefType};
|
use super::{_ConstMutSwitchUiTableHeaderCallback, RefType, _ConstMutSwitchUiTableCallback};
|
||||||
use eframe::emath::Numeric;
|
use eframe::emath::Numeric;
|
||||||
use std::ops::RangeInclusive;
|
use std::ops::RangeInclusive;
|
||||||
|
|
||||||
@ -41,7 +41,7 @@ pub trait ConstMutSwitchUi {
|
|||||||
&mut self,
|
&mut self,
|
||||||
vscroll: bool,
|
vscroll: bool,
|
||||||
columns: usize,
|
columns: usize,
|
||||||
header: impl _ConstMutSwitchUiTableHeaderCallback<Self::RefType>,
|
scope: impl _ConstMutSwitchUiTableCallback<Self::RefType>,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -835,3 +835,176 @@ trait Ctx_Graph<G> {
|
|||||||
// ...
|
// ...
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## 7
|
||||||
|
Метод `_ConstMutSwitchUiTableHeaderCallback::render_header` принимает в себя контекст отрисовки
|
||||||
|
строки и возвращает `impl Trait`. По умолчанию компилятор считает, что возвращаемое значение
|
||||||
|
заимствует все переданные ссылки. Для более тонкой настройки компилятора есть синтаксис
|
||||||
|
`impl Trait + use<'a, A>`, но так как компилятор не способен реализовать минимум, определяемый
|
||||||
|
спецификацией языка, в `use` должны быть указаны все типовые параметры (даже неявные). В
|
||||||
|
данном случае контекст отрисовки туда попадать не должен, так что пришлось отказаться от короткого
|
||||||
|
и удобно способа и вернуться к этапу `3.1`: ручной вызов отрисовки заголовка и тела таблицы.
|
||||||
|
|
||||||
|
## 8
|
||||||
|
### 8.1
|
||||||
|
|
||||||
|
Попытки победить borrow checker в итераторах привели к идее указывать возвращаемый
|
||||||
|
тип итератора в параметре трейта, а не ассоциированным типом.
|
||||||
|
```rust
|
||||||
|
trait LambdaIterator<Item> {
|
||||||
|
fn next<R>(&mut self, receiver: impl FnOnce(Item) -> R) -> Option<R>;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
Это помогло решить некоторые
|
||||||
|
проблемы, но имплементировать такой трейт всё равно не получилось.
|
||||||
|
|
||||||
|
### 8.2
|
||||||
|
Gemini рассказал про **Higher-Rank Trait Bounds (HRTB)**, и вроде как это решает проблему
|
||||||
|
```rust
|
||||||
|
trait LambdaIterator {
|
||||||
|
type Item<'x>;
|
||||||
|
|
||||||
|
fn next<R>(&mut self, receiver: impl for<'x> FnOnce(Self::Item<'x>) -> R) -> Option<R>;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 8.3
|
||||||
|
Имплементация итератора в таком варианте выдавала ошибку, которая исправляется вполне логичным
|
||||||
|
дополнением к трейту:
|
||||||
|
```rust
|
||||||
|
trait LambdaIterator {
|
||||||
|
type Item<'x>: where Self: 'x;
|
||||||
|
|
||||||
|
fn next<R>(&mut self, receiver: impl for<'x> FnOnce(Self::Item<'x>) -> R) -> Option<R>;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 8.4
|
||||||
|
После многочисленных экспериментов был сделан вывод, что язык пока не готов к описанию таких
|
||||||
|
гениальных вещей: или в компиляторе просто с ошибками эти вещи реализованы; или вывод об
|
||||||
|
ошибках недостаточно подробный, чтоб разобраться не употребляя те же вещества, что и создатели.
|
||||||
|
Порождение итератора выглядит следующим образом:
|
||||||
|
```rust
|
||||||
|
trait Ctx_Graph<G> {
|
||||||
|
type RefType: RefType;
|
||||||
|
|
||||||
|
type Vertex<'v>;
|
||||||
|
|
||||||
|
fn iter_vertices<'g>(
|
||||||
|
&mut self,
|
||||||
|
graph: &'g mut G
|
||||||
|
) -> impl for<'v> LambdaIterator<Item<'v>=(&'v mut Self, Self::Vertex<'v>)> + 'g;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
Корректна ли эта запись на практике проверить не удалось, так как в имплементации компилятор
|
||||||
|
просчитывает время жизни лямбды (или её компонентов) совсем не так, как ожидается.
|
||||||
|
|
||||||
|
|
||||||
|
### 8.5
|
||||||
|
Поитогу пришлось откатиться обратно на обычные итераторы. Точнее, на их модифицированную
|
||||||
|
версию, благо знание об HRTB даёт недосающие инструменты:
|
||||||
|
```rust
|
||||||
|
trait GatIterator {
|
||||||
|
type Item<'x>
|
||||||
|
where
|
||||||
|
Self: 'x;
|
||||||
|
|
||||||
|
fn next<'s>(&'s mut self) -> Option<Self::Item<'s>>;
|
||||||
|
|
||||||
|
fn forEach(mut self, mut consumer: impl for<'x> FnMut(Self::Item<'x>))
|
||||||
|
where
|
||||||
|
Self: Sized,
|
||||||
|
{
|
||||||
|
loop {
|
||||||
|
match self.next() {
|
||||||
|
None => return,
|
||||||
|
Some(i) => consumer(i)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 8.6
|
||||||
|
В целом такая модификация итератора работает сама по себе, но использовать его как часть системы
|
||||||
|
трейтов, которые явно указывают какой тип должен возвращать такой итератор не получается, из-за
|
||||||
|
тех же ошибок про неправильное время жизни ассоциированного типа двоюродного племянника бабушки
|
||||||
|
по папиной/маминой линии детей типового параметра.
|
||||||
|
```rust
|
||||||
|
trait Container {
|
||||||
|
type Item<'x>: Contraint;
|
||||||
|
|
||||||
|
fn iter(&mut self) -> impl for<'x> GatIterator<Item<'x> = Self::Item<'x>>;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
Но если создавать под каждую задачу свой трейт итератора, то это как минимум компилируется, но
|
||||||
|
опять же, только в случаях когда не нужно указывать тип элемента в месте использования. Такой
|
||||||
|
модификации подвергся итератор для строк таблицы:
|
||||||
|
```rust
|
||||||
|
|
||||||
|
pub trait ConstMutSwitchUiTable {
|
||||||
|
// ...
|
||||||
|
|
||||||
|
fn body(&mut self, scope: impl _ConstMutSwitchUiTableRowsIterator<Self::RefType>);
|
||||||
|
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait _ConstMutSwitchUiTableRowsIterator<RefType: super::RefType> {
|
||||||
|
type Item<'x>: _ConstMutSwitchUiTableRowCallback<RefType>
|
||||||
|
where
|
||||||
|
Self: 'x;
|
||||||
|
|
||||||
|
fn next<'s>(&'s mut self) -> Option<Self::Item<'s>>;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 9
|
||||||
|
Контекст для работы с графами пришлось несколько раз декомпозировать и изменять, в основном по
|
||||||
|
той же причине невозможности полноценно использовать `+ use<>`. В конечном итоге он превратился
|
||||||
|
просто в обёртку над графом (и его частями) без вынесения в контекст.
|
||||||
|
|
||||||
|
```rust
|
||||||
|
|
||||||
|
pub trait Graph {
|
||||||
|
type RefType: RefType;
|
||||||
|
|
||||||
|
fn iter_vertices(&mut self) -> impl VerticesIterator<RefType = Self::RefType>;
|
||||||
|
|
||||||
|
fn vertices_count(&self) -> usize;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait VerticesIterator {
|
||||||
|
type RefType: RefType;
|
||||||
|
|
||||||
|
type Vertex<'v>: Vertex<RefType = Self::RefType>
|
||||||
|
where
|
||||||
|
Self: 'v;
|
||||||
|
|
||||||
|
fn next<'v>(&'v mut self) -> Option<Self::Vertex<'v>>;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait Vertex {
|
||||||
|
type RefType: RefType;
|
||||||
|
|
||||||
|
fn iter_edges_or_nothing_sorted(&mut self) -> impl EdgesIterator<RefType = Self::RefType>;
|
||||||
|
|
||||||
|
fn set_vertex_to_update_state(&self, state: &mut UpdatePending);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait EdgesIterator {
|
||||||
|
type RefType: RefType;
|
||||||
|
|
||||||
|
type Edge<'e>: Edge<RefType = Self::RefType>
|
||||||
|
where
|
||||||
|
Self: 'e;
|
||||||
|
|
||||||
|
fn next<'e>(&'e mut self) -> Option<Option<Self::Edge<'e>>>;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait Edge {
|
||||||
|
type RefType: RefType;
|
||||||
|
|
||||||
|
fn get_edge_len_ptr<'s>(&'s mut self) -> <Self::RefType as RefType>::Ref<'s, f64>;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|||||||
190
utility/src/gui/graph_lengths_table/ctx.rs
Normal file
190
utility/src/gui/graph_lengths_table/ctx.rs
Normal file
@ -0,0 +1,190 @@
|
|||||||
|
use crate::graph::{CompleteGraph, EdgesVec};
|
||||||
|
use crate::gui::const_mut_switch::{MutRef, RefType};
|
||||||
|
use crate::{GatIterator, UpdatePending};
|
||||||
|
use std::collections::HashSet;
|
||||||
|
use std::ops::IndexMut;
|
||||||
|
use std::ptr::NonNull;
|
||||||
|
|
||||||
|
pub trait Graph {
|
||||||
|
type RefType: RefType;
|
||||||
|
|
||||||
|
fn iter_vertices(&mut self) -> impl VerticesIterator<RefType = Self::RefType>;
|
||||||
|
|
||||||
|
fn vertices_count(&self) -> usize;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait VerticesIterator {
|
||||||
|
type RefType: RefType;
|
||||||
|
|
||||||
|
type Vertex<'v>: Vertex<RefType = Self::RefType>
|
||||||
|
where
|
||||||
|
Self: 'v;
|
||||||
|
|
||||||
|
fn next<'v>(&'v mut self) -> Option<Self::Vertex<'v>>;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait Vertex {
|
||||||
|
type RefType: RefType;
|
||||||
|
|
||||||
|
fn iter_edges_or_nothing_sorted(&mut self) -> impl EdgesIterator<RefType = Self::RefType>;
|
||||||
|
|
||||||
|
fn set_vertex_to_update_state(&self, state: &mut UpdatePending);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait EdgesIterator {
|
||||||
|
type RefType: RefType;
|
||||||
|
|
||||||
|
type Edge<'e>: Edge<RefType = Self::RefType>
|
||||||
|
where
|
||||||
|
Self: 'e;
|
||||||
|
|
||||||
|
fn next<'e>(&'e mut self) -> Option<Option<Self::Edge<'e>>>;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait Edge {
|
||||||
|
type RefType: RefType;
|
||||||
|
|
||||||
|
fn get_edge_len_ptr<'s>(&'s mut self) -> <Self::RefType as RefType>::Ref<'s, f64>;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct MutableGraph<'g> {
|
||||||
|
graph: &'g mut CompleteGraph<()>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Graph for MutableGraph<'_> {
|
||||||
|
type RefType = MutRef;
|
||||||
|
|
||||||
|
fn iter_vertices(&mut self) -> impl VerticesIterator<RefType = Self::RefType> {
|
||||||
|
return MutableVerticesIterator {
|
||||||
|
ee: &mut self.graph.edges,
|
||||||
|
it: self.graph.vertices.iter_indexed_mut(),
|
||||||
|
ordinal: 0,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn vertices_count(&self) -> usize {
|
||||||
|
return self.graph.vertex_count();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct MutableVerticesIterator<'g, It: Iterator<Item = (usize, &'g mut HashSet<usize>)>> {
|
||||||
|
ee: &'g mut EdgesVec<()>,
|
||||||
|
it: It,
|
||||||
|
ordinal: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'g, It: Iterator<Item = (usize, &'g mut HashSet<usize>)>> VerticesIterator
|
||||||
|
for MutableVerticesIterator<'g, It>
|
||||||
|
{
|
||||||
|
type RefType = MutRef;
|
||||||
|
type Vertex<'v>
|
||||||
|
= MutableVertex<'v>
|
||||||
|
where
|
||||||
|
Self: 'v;
|
||||||
|
|
||||||
|
fn next<'v>(&'v mut self) -> Option<Self::Vertex<'v>> {
|
||||||
|
return self.it.next().map(|(i, e)| {
|
||||||
|
let v = MutableVertex {
|
||||||
|
id: i,
|
||||||
|
local_edges: e,
|
||||||
|
all_edges: self.ee,
|
||||||
|
ordinal: self.ordinal,
|
||||||
|
};
|
||||||
|
self.ordinal += 1;
|
||||||
|
return v;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct MutableVertex<'g> {
|
||||||
|
ordinal: usize,
|
||||||
|
id: usize,
|
||||||
|
local_edges: &'g mut HashSet<usize>,
|
||||||
|
all_edges: &'g mut EdgesVec<()>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Vertex for MutableVertex<'_> {
|
||||||
|
type RefType = MutRef;
|
||||||
|
|
||||||
|
fn iter_edges_or_nothing_sorted(&mut self) -> impl EdgesIterator<RefType = Self::RefType> {
|
||||||
|
let mut local_edges = self
|
||||||
|
.local_edges
|
||||||
|
.iter()
|
||||||
|
.map(|i| {
|
||||||
|
(i, unsafe {
|
||||||
|
NonNull::from_mut(self.all_edges.index_mut(0)).as_mut()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.map(|(i, e)| (e.another(self.id), i, &mut e.length))
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
local_edges.sort_by_key(|(k, _, _)| *k);
|
||||||
|
|
||||||
|
return MutableEdgesIterator {
|
||||||
|
it: IteratorWithHole {
|
||||||
|
it: local_edges.into_iter().map(|(_, _, x)| x),
|
||||||
|
hole: Some(self.ordinal),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_vertex_to_update_state(&self, state: &mut UpdatePending) {
|
||||||
|
*state = UpdatePending::Remove(self.id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct IteratorWithHole<E, It: Iterator<Item = E>> {
|
||||||
|
hole: Option<usize>,
|
||||||
|
it: It,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<E, It: Iterator<Item = E>> Iterator for IteratorWithHole<E, It> {
|
||||||
|
type Item = Option<E>;
|
||||||
|
|
||||||
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
|
match self.hole {
|
||||||
|
None => return self.it.next().map(|e| Some(e)),
|
||||||
|
Some(v) => {
|
||||||
|
if v == 0 {
|
||||||
|
self.hole = None;
|
||||||
|
return Some(None);
|
||||||
|
} else {
|
||||||
|
self.hole = Some(v - 1);
|
||||||
|
return self.it.next().map(|e| Some(e));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct MutableEdgesIterator<'g, It: Iterator<Item = Option<(&'g mut f64)>>> {
|
||||||
|
it: It,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'g, It: Iterator<Item = Option<(&'g mut f64)>>> EdgesIterator
|
||||||
|
for MutableEdgesIterator<'g, It>
|
||||||
|
{
|
||||||
|
type RefType = MutRef;
|
||||||
|
type Edge<'x>
|
||||||
|
= MutableEdge<'x>
|
||||||
|
where
|
||||||
|
Self: 'x;
|
||||||
|
|
||||||
|
fn next<'s>(&'s mut self) -> Option<Option<Self::Edge<'s>>> {
|
||||||
|
return self
|
||||||
|
.it
|
||||||
|
.next()
|
||||||
|
.map(|oi| oi.map(|len| MutableEdge { len: len }));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct MutableEdge<'g> {
|
||||||
|
len: &'g mut f64,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Edge for MutableEdge<'_> {
|
||||||
|
type RefType = MutRef;
|
||||||
|
|
||||||
|
fn get_edge_len_ptr<'s>(&'s mut self) -> <Self::RefType as RefType>::Ref<'s, f64> {
|
||||||
|
return self.len;
|
||||||
|
}
|
||||||
|
}
|
||||||
4
utility/src/gui/graph_lengths_table/mod.rs
Normal file
4
utility/src/gui/graph_lengths_table/mod.rs
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
mod ui;
|
||||||
|
mod ctx;
|
||||||
|
|
||||||
|
pub use ctx::{Graph, Vertex, Edge, EdgesIterator, VerticesIterator};
|
||||||
173
utility/src/gui/graph_lengths_table/ui.rs
Normal file
173
utility/src/gui/graph_lengths_table/ui.rs
Normal file
@ -0,0 +1,173 @@
|
|||||||
|
use crate::gat_iterator::GatIterator;
|
||||||
|
use crate::gui::const_mut_switch::{ConstMutSwitchUi, ConstMutSwitchUiTable, ConstMutSwitchUiTableRow, RefType, _ConstMutSwitchUiCallback, _ConstMutSwitchUiTableCallback, _ConstMutSwitchUiTableHeaderCallback, _ConstMutSwitchUiTableRowCallback, _ConstMutSwitchUiTableRowsIterator};
|
||||||
|
use crate::gui::graph_lengths_table::ctx::EdgesIterator;
|
||||||
|
use crate::gui::graph_lengths_table::ctx::VerticesIterator;
|
||||||
|
use crate::gui::graph_lengths_table::{Edge, Graph, Vertex};
|
||||||
|
use crate::{LambdaIterator, UpdatePending};
|
||||||
|
|
||||||
|
pub fn draw_lengths_table<G: Graph, CtxUi: ConstMutSwitchUi<RefType = G::RefType>>(
|
||||||
|
ctx_ui: &mut CtxUi,
|
||||||
|
graph: &mut G,
|
||||||
|
update: <CtxUi::RefType as RefType>::Ref<'_, UpdatePending>,
|
||||||
|
) {
|
||||||
|
ctx_ui.scroll_area_2(Root { graph, update });
|
||||||
|
}
|
||||||
|
struct Root<'g, 'u, G: Graph> {
|
||||||
|
graph: &'g mut G,
|
||||||
|
update: <G::RefType as RefType>::Ref<'u, UpdatePending>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<G: Graph> _ConstMutSwitchUiCallback<G::RefType> for Root<'_, '_, G> {
|
||||||
|
fn render(self, ctx: &mut impl ConstMutSwitchUi<RefType = G::RefType>) {
|
||||||
|
ctx.table(false, self.graph.vertices_count(), self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<G: Graph> _ConstMutSwitchUiTableCallback<G::RefType> for Root<'_, '_, G> {
|
||||||
|
fn render_table(mut self, ctx: &mut impl ConstMutSwitchUiTable<RefType = G::RefType>) {
|
||||||
|
ctx.header(Header {
|
||||||
|
it: self.graph.iter_vertices(),
|
||||||
|
update: &mut self.update,
|
||||||
|
});
|
||||||
|
|
||||||
|
ctx.body(RowsIterators {
|
||||||
|
vertices: self.graph.iter_vertices(),
|
||||||
|
update: self.update,
|
||||||
|
row_id: 0,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Header<'u, 'uu, It: VerticesIterator> {
|
||||||
|
it: It,
|
||||||
|
update: &'uu mut <It::RefType as RefType>::Ref<'u, UpdatePending>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<It: VerticesIterator> _ConstMutSwitchUiTableHeaderCallback<It::RefType>
|
||||||
|
for Header<'_, '_, It>
|
||||||
|
{
|
||||||
|
fn render_header(mut self, row: &mut impl ConstMutSwitchUiTableRow<RefType = It::RefType>) {
|
||||||
|
row.cell(CornerCell {});
|
||||||
|
|
||||||
|
let mut column_id = 0;
|
||||||
|
loop {
|
||||||
|
match self.it.next() {
|
||||||
|
None => break,
|
||||||
|
Some(mut v) => {
|
||||||
|
column_id += 1;
|
||||||
|
// let update = &mut self.update;
|
||||||
|
let data = TitleCell {
|
||||||
|
row_id: column_id,
|
||||||
|
vertex: &mut v,
|
||||||
|
update: &mut self.update,
|
||||||
|
};
|
||||||
|
row.cell(data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
struct RowsIterators<'u, It: VerticesIterator> {
|
||||||
|
vertices: It,
|
||||||
|
update: <It::RefType as RefType>::Ref<'u, UpdatePending>,
|
||||||
|
row_id: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'u, It: VerticesIterator> RowsIterators<'u, It> {
|
||||||
|
fn next<'s>(&'s mut self) -> Option<Row<'s, 'u, It::Vertex<'s>>> {
|
||||||
|
match self.vertices.next() {
|
||||||
|
None => return None,
|
||||||
|
Some(v) => {
|
||||||
|
self.row_id += 1;
|
||||||
|
return Some(Row {
|
||||||
|
vertex: v,
|
||||||
|
row_id: self.row_id,
|
||||||
|
update: &mut self.update,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<'u, It: VerticesIterator> _ConstMutSwitchUiTableRowsIterator<It::RefType> for RowsIterators<'u, It> {
|
||||||
|
type Item<'x>
|
||||||
|
= Row<'x, 'u, It::Vertex<'x>>
|
||||||
|
where
|
||||||
|
Self: 'x;
|
||||||
|
|
||||||
|
fn next<'s>(&'s mut self) -> Option<Self::Item<'s>> {
|
||||||
|
match self.vertices.next() {
|
||||||
|
None => return None,
|
||||||
|
Some(v) => {
|
||||||
|
self.row_id += 1;
|
||||||
|
return Some(Row {
|
||||||
|
vertex: v,
|
||||||
|
row_id: self.row_id,
|
||||||
|
update: &mut self.update,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Row<'uu, 'u: 'uu, V: Vertex> {
|
||||||
|
vertex: V,
|
||||||
|
row_id: usize,
|
||||||
|
update: &'uu mut <V::RefType as RefType>::Ref<'u, UpdatePending>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<V: Vertex> _ConstMutSwitchUiTableRowCallback<V::RefType> for Row<'_, '_, V> {
|
||||||
|
fn render_row(mut self, row: &mut impl ConstMutSwitchUiTableRow<RefType = V::RefType>) {
|
||||||
|
row.cell(TitleCell {
|
||||||
|
row_id: self.row_id,
|
||||||
|
vertex: &mut self.vertex,
|
||||||
|
update: self.update,
|
||||||
|
});
|
||||||
|
|
||||||
|
let mut it = self.vertex.iter_edges_or_nothing_sorted();
|
||||||
|
|
||||||
|
loop {
|
||||||
|
match it.next() {
|
||||||
|
None => break,
|
||||||
|
Some(None) => row.cell(EmptyCell {}),
|
||||||
|
Some(Some(mut e)) => row.cell(LengthCell {
|
||||||
|
length: &mut e.get_edge_len_ptr(),
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct CornerCell {}
|
||||||
|
impl<RT: RefType> _ConstMutSwitchUiCallback<RT> for CornerCell {
|
||||||
|
fn render(self, ctx: &mut impl ConstMutSwitchUi<RefType = RT>) {
|
||||||
|
ctx.label("#");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct TitleCell<'v, 'uu, 'u: 'uu, V: Vertex> {
|
||||||
|
row_id: usize,
|
||||||
|
vertex: &'v mut V,
|
||||||
|
update: &'uu mut <V::RefType as RefType>::Ref<'u, UpdatePending>,
|
||||||
|
}
|
||||||
|
impl<V: Vertex> _ConstMutSwitchUiCallback<V::RefType> for TitleCell<'_, '_, '_, V> {
|
||||||
|
fn render(self, ctx: &mut impl ConstMutSwitchUi<RefType = V::RefType>) {
|
||||||
|
ctx.label(self.row_id.to_string().as_str());
|
||||||
|
ctx.button("-", self.update, |s| {
|
||||||
|
self.vertex.set_vertex_to_update_state(s)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct LengthCell<'rr, 'r: 'rr, RT: RefType> {
|
||||||
|
length: &'rr mut RT::Ref<'r, f64>,
|
||||||
|
}
|
||||||
|
impl<RT: RefType> _ConstMutSwitchUiCallback<RT> for LengthCell<'_, '_, RT> {
|
||||||
|
fn render(self, ctx: &mut impl ConstMutSwitchUi<RefType = RT>) {
|
||||||
|
ctx.slider(0.0..=10.0, 0.1, self.length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct EmptyCell {}
|
||||||
|
impl<RT: RefType> _ConstMutSwitchUiCallback<RT> for EmptyCell {
|
||||||
|
fn render(self, _: &mut impl ConstMutSwitchUi<RefType = RT>) {}
|
||||||
|
}
|
||||||
@ -1,201 +0,0 @@
|
|||||||
use crate::gui::const_mut_switch::{
|
|
||||||
_ConstMutSwitchUiCallback, _ConstMutSwitchUiTableHeaderCallback,
|
|
||||||
_ConstMutSwitchUiTableRowCallback, ConstMutSwitchUi, ConstMutSwitchUiTableRow, RefType,
|
|
||||||
};
|
|
||||||
use crate::{LambdaIterator, UpdatePending};
|
|
||||||
use std::ptr::NonNull;
|
|
||||||
|
|
||||||
pub trait Ctx_Graph<G> {
|
|
||||||
type RefType: RefType;
|
|
||||||
|
|
||||||
type Vertex;
|
|
||||||
type VerticesIterator<'a>: LambdaIterator<Item=(&'a mut Self, Self::Vertex)>
|
|
||||||
where
|
|
||||||
Self: 'a;
|
|
||||||
fn iter_vertices(&mut self, graph: &mut G) -> Self::VerticesIterator<'_>;
|
|
||||||
|
|
||||||
type Edge;
|
|
||||||
fn iter_edges_or_nothing(
|
|
||||||
&mut self,
|
|
||||||
vertex: &mut Self::Vertex,
|
|
||||||
) -> impl LambdaIterator<Item=(&mut Self, Option<Self::Edge>)>;
|
|
||||||
|
|
||||||
fn get_edge_len_ptr(
|
|
||||||
&mut self,
|
|
||||||
edge: &mut Self::Edge,
|
|
||||||
) -> <Self::RefType as RefType>::Ref<'_, f64>;
|
|
||||||
|
|
||||||
fn set_vertex_to_update_state(&self, vertex: &Self::Vertex, state: &mut UpdatePending);
|
|
||||||
|
|
||||||
fn vertices_count(&self) -> usize;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn draw_lengths_table<
|
|
||||||
G,
|
|
||||||
CtxUi: ConstMutSwitchUi,
|
|
||||||
CtxGraph: Ctx_Graph<G, RefType=CtxUi::RefType>,
|
|
||||||
>(
|
|
||||||
ctx_ui: &mut CtxUi,
|
|
||||||
ctx_graph: &mut CtxGraph,
|
|
||||||
graph: G,
|
|
||||||
update: <CtxUi::RefType as RefType>::Ref<'_, UpdatePending>,
|
|
||||||
) {
|
|
||||||
ctx_ui.scroll_area_2(ScrollArea {
|
|
||||||
ctx_graph,
|
|
||||||
graph,
|
|
||||||
update,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
struct ScrollArea<'g, 'u, G, CtxGraph: Ctx_Graph<G>> {
|
|
||||||
ctx_graph: &'g mut CtxGraph,
|
|
||||||
graph: G,
|
|
||||||
update: <CtxGraph::RefType as RefType>::Ref<'u, UpdatePending>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<G, CtxGraph: Ctx_Graph<G>> _ConstMutSwitchUiCallback<CtxGraph::RefType>
|
|
||||||
for ScrollArea<'_, '_, G, CtxGraph>
|
|
||||||
{
|
|
||||||
fn render(self, ctx: &mut impl ConstMutSwitchUi<RefType=CtxGraph::RefType>) {
|
|
||||||
ctx.table(
|
|
||||||
false,
|
|
||||||
self.ctx_graph.vertices_count(),
|
|
||||||
Header {
|
|
||||||
ctx_graph: self.ctx_graph,
|
|
||||||
graph: self.graph,
|
|
||||||
update: self.update,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Header<'g, 'u, G, CtxGraph: Ctx_Graph<G>> {
|
|
||||||
ctx_graph: &'g mut CtxGraph,
|
|
||||||
graph: G,
|
|
||||||
update: <CtxGraph::RefType as RefType>::Ref<'u, UpdatePending>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'g, 'u, G, CtxGraph: Ctx_Graph<G>> _ConstMutSwitchUiTableHeaderCallback<CtxGraph::RefType>
|
|
||||||
for Header<'g, 'u, G, CtxGraph>
|
|
||||||
{
|
|
||||||
type RowRender = Row<'g, 'u, G, CtxGraph>;
|
|
||||||
|
|
||||||
type RowsIterator = RowsIterators<'g, 'u, G, CtxGraph>;
|
|
||||||
|
|
||||||
fn render_header(
|
|
||||||
mut self,
|
|
||||||
row: &mut impl ConstMutSwitchUiTableRow<RefType=CtxGraph::RefType>,
|
|
||||||
) -> Self::RowsIterator {
|
|
||||||
row.cell(CornerCell {});
|
|
||||||
|
|
||||||
let mut column_id = 0;
|
|
||||||
self.ctx_graph
|
|
||||||
.iter_vertices(&mut self.graph)
|
|
||||||
.consume(|(ctx_graph, v)| {
|
|
||||||
column_id += 1;
|
|
||||||
// let update = &mut self.update;
|
|
||||||
let data = TitleCell {
|
|
||||||
ctx_graph: ctx_graph,
|
|
||||||
row_id: column_id,
|
|
||||||
vertex: &v,
|
|
||||||
update: &mut self.update,
|
|
||||||
};
|
|
||||||
row.cell(data)
|
|
||||||
});
|
|
||||||
|
|
||||||
return RowsIterators {
|
|
||||||
vertices: self.ctx_graph.iter_vertices(&mut self.graph),
|
|
||||||
update: self.update,
|
|
||||||
row_id: 0,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
struct RowsIterators<'g, 'u, G, CtxGraph: Ctx_Graph<G> + 'g> {
|
|
||||||
vertices: CtxGraph::VerticesIterator<'g>,
|
|
||||||
update: <CtxGraph::RefType as RefType>::Ref<'u, UpdatePending>,
|
|
||||||
row_id: usize,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'g, 'u, G, CtxGraph: Ctx_Graph<G> + 'g> LambdaIterator for RowsIterators<'g, 'u, G, CtxGraph> {
|
|
||||||
type Item = Row<'g, 'u, G, CtxGraph>;
|
|
||||||
|
|
||||||
fn next<R>(&mut self, receiver: impl FnOnce(Self::Item) -> R) -> Option<R> {
|
|
||||||
return self.vertices.next(|(ctx, v)| {
|
|
||||||
self.row_id += 1;
|
|
||||||
return receiver(Row {
|
|
||||||
ctx_graph: ctx,
|
|
||||||
vertex: v,
|
|
||||||
row_id: self.row_id,
|
|
||||||
update: NonNull::from_mut(&mut self.update),
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Row<'g, 'u, G, CtxGraph: Ctx_Graph<G>> {
|
|
||||||
ctx_graph: &'g mut CtxGraph,
|
|
||||||
vertex: CtxGraph::Vertex,
|
|
||||||
row_id: usize,
|
|
||||||
update: NonNull<<CtxGraph::RefType as RefType>::Ref<'u, UpdatePending>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<G, CtxGraph: Ctx_Graph<G>> _ConstMutSwitchUiTableRowCallback<CtxGraph::RefType>
|
|
||||||
for Row<'_, '_, G, CtxGraph>
|
|
||||||
{
|
|
||||||
fn render_row(mut self, row: &mut impl ConstMutSwitchUiTableRow<RefType=CtxGraph::RefType>) {
|
|
||||||
row.cell(TitleCell {
|
|
||||||
ctx_graph: self.ctx_graph,
|
|
||||||
row_id: self.row_id,
|
|
||||||
vertex: &self.vertex,
|
|
||||||
update: unsafe { self.update.as_mut() },
|
|
||||||
});
|
|
||||||
|
|
||||||
self.ctx_graph
|
|
||||||
.iter_edges_or_nothing(&mut self.vertex)
|
|
||||||
.consume(|(ctx_graph, e)| {
|
|
||||||
match e {
|
|
||||||
None => row.cell(EmptyCell {}),
|
|
||||||
Some(mut e) => row.cell(LengthCell {
|
|
||||||
length: &mut ctx_graph.get_edge_len_ptr(&mut e),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct CornerCell {}
|
|
||||||
impl<RT: RefType> _ConstMutSwitchUiCallback<RT> for CornerCell {
|
|
||||||
fn render(self, ctx: &mut impl ConstMutSwitchUi<RefType=RT>) {
|
|
||||||
ctx.label("#");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct TitleCell<'g, 'v, 'rr, 'r: 'rr, G, CtxGraph: Ctx_Graph<G>> {
|
|
||||||
ctx_graph: &'g mut CtxGraph,
|
|
||||||
row_id: usize,
|
|
||||||
vertex: &'v CtxGraph::Vertex,
|
|
||||||
update: &'rr mut <CtxGraph::RefType as RefType>::Ref<'r, UpdatePending>,
|
|
||||||
}
|
|
||||||
impl<G, CtxGraph: Ctx_Graph<G>> _ConstMutSwitchUiCallback<CtxGraph::RefType>
|
|
||||||
for TitleCell<'_, '_, '_, '_, G, CtxGraph>
|
|
||||||
{
|
|
||||||
fn render(self, ctx: &mut impl ConstMutSwitchUi<RefType=CtxGraph::RefType>) {
|
|
||||||
ctx.label(self.row_id.to_string().as_str());
|
|
||||||
ctx.button("-", self.update, |s| {
|
|
||||||
self.ctx_graph.set_vertex_to_update_state(self.vertex, s)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct LengthCell<'rr, 'r: 'rr, RT: RefType> {
|
|
||||||
length: &'rr mut RT::Ref<'r, f64>,
|
|
||||||
}
|
|
||||||
impl<RT: RefType> _ConstMutSwitchUiCallback<RT> for LengthCell<'_, '_, RT> {
|
|
||||||
fn render(self, ctx: &mut impl ConstMutSwitchUi<RefType=RT>) {
|
|
||||||
ctx.slider(0.0..=10.0, 0.1, self.length);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct EmptyCell {}
|
|
||||||
impl<RT: RefType> _ConstMutSwitchUiCallback<RT> for EmptyCell {
|
|
||||||
fn render(self, _: &mut impl ConstMutSwitchUi<RefType=RT>) {}
|
|
||||||
}
|
|
||||||
@ -1,9 +1,9 @@
|
|||||||
mod boot;
|
mod boot;
|
||||||
pub mod const_mut_switch;
|
pub mod const_mut_switch;
|
||||||
pub mod lengths_table;
|
|
||||||
mod render_graph;
|
mod render_graph;
|
||||||
mod slider;
|
mod slider;
|
||||||
mod subwindow;
|
mod subwindow;
|
||||||
|
mod graph_lengths_table;
|
||||||
|
|
||||||
pub use boot::boot_eframe;
|
pub use boot::boot_eframe;
|
||||||
pub use render_graph::render_graph;
|
pub use render_graph::render_graph;
|
||||||
|
|||||||
@ -1,9 +1,9 @@
|
|||||||
pub trait LambdaIterator {
|
pub trait LambdaIterator {
|
||||||
type Item;
|
type Item<'x>: where Self: 'x;
|
||||||
|
|
||||||
fn next<R>(&mut self, receiver: impl FnOnce(Self::Item) -> R) -> Option<R>;
|
fn next<R>(&mut self, receiver: impl for<'x> FnOnce(Self::Item<'x>) -> R) -> Option<R>;
|
||||||
|
|
||||||
fn consume(mut self, mut receiver: impl FnMut(Self::Item))
|
fn consume(mut self, mut receiver: impl for<'x> FnMut(Self::Item<'x>))
|
||||||
where
|
where
|
||||||
Self: Sized,
|
Self: Sized,
|
||||||
{
|
{
|
||||||
@ -11,7 +11,7 @@ pub trait LambdaIterator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn make_lambda<I: Iterator>(it: I) -> impl LambdaIterator<Item = I::Item> {
|
/*pub fn make_lambda<'z, I: Iterator>(it: I) -> impl for<'x> LambdaIterator<Item<'x> = I::Item> {
|
||||||
return LambdaIteratorConverter { it };
|
return LambdaIteratorConverter { it };
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -20,9 +20,10 @@ struct LambdaIteratorConverter<I: Iterator> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<I: Iterator> LambdaIterator for LambdaIteratorConverter<I> {
|
impl<I: Iterator> LambdaIterator for LambdaIteratorConverter<I> {
|
||||||
type Item = I::Item;
|
type Item<'x> = I::Item where Self:'x;
|
||||||
|
|
||||||
fn next<R>(&mut self, receiver: impl FnOnce(Self::Item) -> R) -> Option<R> {
|
fn next<'s, R>(&mut self, receiver: impl for<'x> FnOnce(I::Item) -> R) -> Option<R> {
|
||||||
return self.it.next().map(receiver);
|
return self.it.next().map(receiver);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
@ -3,7 +3,9 @@ pub mod gui;
|
|||||||
mod lambda_iterator;
|
mod lambda_iterator;
|
||||||
mod update_pending;
|
mod update_pending;
|
||||||
mod weighted_random;
|
mod weighted_random;
|
||||||
|
mod gat_iterator;
|
||||||
|
|
||||||
pub use lambda_iterator::{LambdaIterator, make_lambda};
|
pub use lambda_iterator::{LambdaIterator};
|
||||||
|
pub use gat_iterator::{GatIterator};
|
||||||
pub use update_pending::{UpdatePending, UpdateTarget};
|
pub use update_pending::{UpdatePending, UpdateTarget};
|
||||||
pub use weighted_random::{weighted_random, weighted_random_index};
|
pub use weighted_random::{weighted_random, weighted_random_index};
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user