Attempt 2 to make mutability-independent UI
This commit is contained in:
parent
f295dc7a12
commit
09b732cfbc
@ -1,7 +1,4 @@
|
|||||||
use super::{
|
use super::{_ConstMutSwitchUiCallback, ConstMutSwitchUi, ConstRef, RefType, _ConstMutSwitchUiTableHeaderCallback};
|
||||||
_ConstMutSwitchUiCallback, _ConstMutSwitchUiTableBaseCallback,
|
|
||||||
_ConstMutSwitchUiTableRowCallback, ConstMutSwitchUi, ConstRef, RefType,
|
|
||||||
};
|
|
||||||
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;
|
||||||
@ -52,9 +49,8 @@ impl ConstMutSwitchUi for ConstUI<'_> {
|
|||||||
self.ui.label("");
|
self.ui.label("");
|
||||||
}
|
}
|
||||||
|
|
||||||
fn horizontal<F: _ConstMutSwitchUiCallback<ConstRef>>(&mut self, clojure: &mut F::Clojure<'_>) {
|
fn horizontal(&mut self, scope: impl _ConstMutSwitchUiCallback<ConstRef>) {
|
||||||
self.ui
|
self.ui.horizontal(|ui| scope.render(&mut ConstUI { ui }));
|
||||||
.horizontal(|ui| F::render(&mut ConstUI { ui }, clojure));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn button<T>(&mut self, label: &str, _storage: &mut &T, _on_click: impl FnOnce(&mut T)) {
|
fn button<T>(&mut self, label: &str, _storage: &mut &T, _on_click: impl FnOnce(&mut T)) {
|
||||||
@ -65,33 +61,22 @@ impl ConstMutSwitchUi for ConstUI<'_> {
|
|||||||
self.ui.separator();
|
self.ui.separator();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn scroll_area_2<F: _ConstMutSwitchUiCallback<Self::RefType>>(
|
fn scroll_area_2(
|
||||||
&mut self,
|
&mut self,
|
||||||
clojure: &mut F::Clojure<'_>,
|
scope: impl _ConstMutSwitchUiCallback<Self::RefType>,
|
||||||
) {
|
) {
|
||||||
ScrollArea::both()
|
ScrollArea::both()
|
||||||
.auto_shrink([false, false])
|
.auto_shrink([false, false])
|
||||||
.show_viewport(self.ui, |ui, _| F::render(&mut ConstUI { ui }, clojure));
|
.show_viewport(self.ui, |ui, _|scope.render(&mut ConstUI { ui }));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn table<
|
|
||||||
'a,
|
fn table(
|
||||||
F: _ConstMutSwitchUiTableBaseCallback<ConstRef, Body = _B>,
|
|
||||||
_B: _ConstMutSwitchUiTableRowCallback<ConstRef, Clojure<'a> = _BC>,
|
|
||||||
_BC,
|
|
||||||
>(
|
|
||||||
&mut self,
|
&mut self,
|
||||||
vscroll: bool,
|
vscroll: bool,
|
||||||
columns: usize,
|
columns: usize,
|
||||||
header_clojure: <F::Header as _ConstMutSwitchUiTableRowCallback<ConstRef>>::Clojure<'_>,
|
header: impl _ConstMutSwitchUiTableHeaderCallback<Self::RefType>,
|
||||||
body_data: impl Iterator<Item = _BC>,
|
|
||||||
) {
|
) {
|
||||||
super::render_table::<ConstUI, F, Self>(
|
super::render_table::<ConstRef, Self>(self.ui, vscroll, columns, header);
|
||||||
self.ui,
|
|
||||||
vscroll,
|
|
||||||
columns,
|
|
||||||
header_clojure,
|
|
||||||
body_data,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,9 +6,9 @@ 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, RefGetter, RefType, _IteratorGetter};
|
pub use r#ref::{ConstRef, MutRef, RefType};
|
||||||
use table::render_table;
|
use table::render_table;
|
||||||
pub use table::{
|
pub use table::{
|
||||||
_ConstMutSwitchUiTableBaseCallback, _ConstMutSwitchUiTableRowCallback, ConstMutSwitchUiTableRow,
|
_ConstMutSwitchUiTableHeaderCallback, _ConstMutSwitchUiTableRowCallback, ConstMutSwitchUiTableRow,
|
||||||
};
|
};
|
||||||
pub use r#trait::{_ConstMutSwitchUiCallback, ConstMutSwitchUi};
|
pub use r#trait::{_ConstMutSwitchUiCallback, ConstMutSwitchUi};
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
use super::{ConstMutSwitchUi, MutRef, RefType, _ConstMutSwitchUiTableBaseCallback, _ConstMutSwitchUiTableRowCallback};
|
use super::{_ConstMutSwitchUiTableHeaderCallback, ConstMutSwitchUi, MutRef, RefType};
|
||||||
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;
|
||||||
@ -8,6 +8,12 @@ pub struct MutUI<'ui> {
|
|||||||
ui: &'ui mut Ui,
|
ui: &'ui mut Ui,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'ui> MutUI<'ui> {
|
||||||
|
pub fn wrap(ui: &'ui mut Ui) -> Self {
|
||||||
|
return Self { ui };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl ConstMutSwitchUi for MutUI<'_> {
|
impl ConstMutSwitchUi for MutUI<'_> {
|
||||||
type RefType = MutRef;
|
type RefType = MutRef;
|
||||||
|
|
||||||
@ -15,7 +21,12 @@ impl ConstMutSwitchUi for MutUI<'_> {
|
|||||||
self.ui.label(s);
|
self.ui.label(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn slider<T: Numeric>(&mut self, range: RangeInclusive<T>, step: f64, storage: &mut <Self::RefType as RefType>::Ref<'_, T>) {
|
fn slider<T: Numeric>(
|
||||||
|
&mut self,
|
||||||
|
range: RangeInclusive<T>,
|
||||||
|
step: f64,
|
||||||
|
storage: &mut <Self::RefType as RefType>::Ref<'_, T>,
|
||||||
|
) {
|
||||||
crate::gui::slider(self.ui, *storage, range, step);
|
crate::gui::slider(self.ui, *storage, range, step);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -33,9 +44,8 @@ impl ConstMutSwitchUi for MutUI<'_> {
|
|||||||
self.ui.label("");
|
self.ui.label("");
|
||||||
}
|
}
|
||||||
|
|
||||||
fn horizontal<I: _ConstMutSwitchUiCallback<MutRef>>(&mut self, clojure: &mut I::Clojure<'_>) {
|
fn horizontal(&mut self, scope: impl _ConstMutSwitchUiCallback<MutRef>) {
|
||||||
self.ui
|
self.ui.horizontal(|ui| scope.render(&mut MutUI { ui }));
|
||||||
.horizontal(|ui| I::render(&mut MutUI { ui }, clojure));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn button<T>(&mut self, label: &str, storage: &mut &mut T, on_click: impl FnOnce(&mut T)) {
|
fn button<T>(&mut self, label: &str, storage: &mut &mut T, on_click: impl FnOnce(&mut T)) {
|
||||||
@ -48,27 +58,18 @@ impl ConstMutSwitchUi for MutUI<'_> {
|
|||||||
self.ui.separator();
|
self.ui.separator();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn scroll_area_2<F: _ConstMutSwitchUiCallback<Self::RefType>>(
|
fn scroll_area_2(&mut self, scope: impl _ConstMutSwitchUiCallback<MutRef>) {
|
||||||
&mut self,
|
|
||||||
clojure: &mut F::Clojure<'_>,
|
|
||||||
) {
|
|
||||||
ScrollArea::both()
|
ScrollArea::both()
|
||||||
.auto_shrink([false, false])
|
.auto_shrink([false, false])
|
||||||
.show_viewport(self.ui, |ui, _| F::render(&mut MutUI { ui }, clojure));
|
.show_viewport(self.ui, |ui, _| scope.render(&mut MutUI { ui }));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn table<
|
fn table(
|
||||||
'a,
|
|
||||||
F: _ConstMutSwitchUiTableBaseCallback<MutRef, Body = _B>,
|
|
||||||
_B: _ConstMutSwitchUiTableRowCallback<MutRef, Clojure<'a> = _BC>,
|
|
||||||
_BC,
|
|
||||||
>(
|
|
||||||
&mut self,
|
&mut self,
|
||||||
vscroll: bool,
|
vscroll: bool,
|
||||||
columns: usize,
|
columns: usize,
|
||||||
header_clojure: <F::Header as _ConstMutSwitchUiTableRowCallback<MutRef>>::Clojure<'_>,
|
header: impl _ConstMutSwitchUiTableHeaderCallback<Self::RefType>,
|
||||||
body_data: impl Iterator<Item = _BC>,
|
|
||||||
) {
|
) {
|
||||||
super::render_table::<MutUI, F, Self>(self.ui, vscroll, columns, header_clojure, body_data);
|
super::render_table::<MutRef, Self>(self.ui, vscroll, columns, header);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,9 +1,8 @@
|
|||||||
use crate::gui::const_mut_switch::ConstMutSwitchUi;
|
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
use std::ptr::NonNull;
|
use std::ptr::NonNull;
|
||||||
|
|
||||||
pub trait RefType {
|
pub trait RefType {
|
||||||
type Ref<'a, T: 'a>: Deref<Target = T>;
|
type Ref<'a, T: 'a>: Deref<Target=T>;
|
||||||
|
|
||||||
fn _get<'r, 'f: 'r, 's: 'f, S, M>(
|
fn _get<'r, 'f: 'r, 's: 'f, S, M>(
|
||||||
storge: &'f mut Self::Ref<'s, S>,
|
storge: &'f mut Self::Ref<'s, S>,
|
||||||
@ -13,32 +12,6 @@ pub trait RefType {
|
|||||||
|
|
||||||
unsafe fn _to_ptr<T>(r: Self::Ref<'_, T>) -> NonNull<T>;
|
unsafe fn _to_ptr<T>(r: Self::Ref<'_, T>) -> NonNull<T>;
|
||||||
unsafe fn _from_ptr<'a, T>(r: NonNull<T>) -> Self::Ref<'a, T>;
|
unsafe fn _from_ptr<'a, T>(r: NonNull<T>) -> Self::Ref<'a, T>;
|
||||||
|
|
||||||
fn _iter<'r, 'f: 'r, 's: 'f, F: _IteratorGetter>(
|
|
||||||
storge: &'f mut Self::Ref<'s, F::C>,
|
|
||||||
) -> impl Iterator<Item = Self::Ref<'r, F::T<'r>>>;
|
|
||||||
|
|
||||||
fn _enum_iter<'r, 'f: 'r, 's: 'f, F: _IteratorGetter>(
|
|
||||||
storge: &'f mut Self::Ref<'s, F::C>,
|
|
||||||
) -> impl Iterator<Item = Self::Ref<'r, F::T<'r>>>;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait _IteratorGetter {
|
|
||||||
type C;
|
|
||||||
type T<'a>: 'a;
|
|
||||||
fn get_const_iterator<'a>(cont: &'a Self::C) -> impl Iterator<Item = &Self::T<'a>>;
|
|
||||||
|
|
||||||
fn get_mut_iterator<'a>(cont: &'a mut Self::C) -> impl Iterator<Item = &mut Self::T<'a>>;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait _EnumeratedIteratorGetter {
|
|
||||||
type C;
|
|
||||||
type T<'a>: 'a;
|
|
||||||
fn get_const_iterator<'a>(cont: &'a Self::C) -> impl Iterator<Item = (usize, &Self::T<'a>)>;
|
|
||||||
|
|
||||||
fn get_mut_iterator<'a>(
|
|
||||||
cont: &'a mut Self::C,
|
|
||||||
) -> impl Iterator<Item = (usize, &mut Self::T<'a>)>;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ConstRef {}
|
pub struct ConstRef {}
|
||||||
@ -61,12 +34,6 @@ impl RefType for ConstRef {
|
|||||||
unsafe fn _from_ptr<'a, T>(r: NonNull<T>) -> Self::Ref<'a, T> {
|
unsafe fn _from_ptr<'a, T>(r: NonNull<T>) -> Self::Ref<'a, T> {
|
||||||
return r.as_ref();
|
return r.as_ref();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn _iter<'r, 'f: 'r, 's: 'f, F: _IteratorGetter>(
|
|
||||||
storge: &'f mut Self::Ref<'s, F::C>,
|
|
||||||
) -> impl Iterator<Item = &'r F::T<'r>> {
|
|
||||||
return F::get_const_iterator(storge);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct MutRef {}
|
pub struct MutRef {}
|
||||||
@ -89,18 +56,4 @@ impl RefType for MutRef {
|
|||||||
unsafe fn _from_ptr<'a, T>(mut r: NonNull<T>) -> Self::Ref<'a, T> {
|
unsafe fn _from_ptr<'a, T>(mut r: NonNull<T>) -> Self::Ref<'a, T> {
|
||||||
return r.as_mut();
|
return r.as_mut();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn _iter<'r, 'f: 'r, 's: 'f, F: _IteratorGetter>(
|
|
||||||
storge: &'f mut Self::Ref<'s, F::C>,
|
|
||||||
) -> impl Iterator<Item = &'r mut F::T<'r>> {
|
|
||||||
return F::get_mut_iterator(storge);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait RefGetter {
|
|
||||||
type Ref<'a, T: 'a>;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<C: ConstMutSwitchUi> RefGetter for C {
|
|
||||||
type Ref<'a, T: 'a> = <C::RefType as RefType>::Ref<'a, T>;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,30 +1,32 @@
|
|||||||
use super::{_ConstMutSwitchUiCallback, ConstMutSwitchUi, ConstRef, ConstUI, MutRef, MutUI, RefType};
|
#![allow(deprecated)]
|
||||||
|
|
||||||
|
use super::{
|
||||||
|
_ConstMutSwitchUiCallback, ConstMutSwitchUi, ConstRef, ConstUI, MutRef, MutUI, RefType,
|
||||||
|
};
|
||||||
|
use crate::LambdaIterator;
|
||||||
use eframe::egui::Ui;
|
use eframe::egui::Ui;
|
||||||
use egui_extras::{Column, TableBuilder, TableRow};
|
use egui_extras::{Column, TableBuilder, TableRow};
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
|
use std::mem::uninitialized;
|
||||||
|
|
||||||
pub trait _ConstMutSwitchUiTableBaseCallback<RefType: super::RefType> {
|
pub trait _ConstMutSwitchUiTableHeaderCallback<RefType: super::RefType> {
|
||||||
type Header: _ConstMutSwitchUiTableRowCallback<RefType>;
|
type RowRender: _ConstMutSwitchUiTableRowCallback<RefType>;
|
||||||
type Body: _ConstMutSwitchUiTableRowCallback<RefType>;
|
type RowsIterator: LambdaIterator<Item = Self::RowRender>;
|
||||||
|
|
||||||
fn header_to_body<'a>(
|
fn render_header(
|
||||||
header: &mut <Self::Header as _ConstMutSwitchUiTableRowCallback<RefType>>::Clojure<'a>,
|
self,
|
||||||
) -> impl Iterator<Item = <Self::Body as _ConstMutSwitchUiTableRowCallback<RefType>>::Clojure<'a>>;
|
ctx: &mut impl ConstMutSwitchUiTableRow<RefType = RefType>,
|
||||||
|
) -> Self::RowsIterator;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait _ConstMutSwitchUiTableRowCallback<RefType: super::RefType> {
|
pub trait _ConstMutSwitchUiTableRowCallback<RefType: super::RefType> {
|
||||||
type Clojure<'a>;
|
fn render_row(self, row: &mut impl ConstMutSwitchUiTableRow<RefType = RefType>);
|
||||||
|
|
||||||
fn render_row<Row: ConstMutSwitchUiTableRow<RefType = RefType>>(
|
|
||||||
row: &mut Row,
|
|
||||||
clojure: &mut Self::Clojure<'_>,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait ConstMutSwitchUiTableRow {
|
pub trait ConstMutSwitchUiTableRow {
|
||||||
type RefType: RefType;
|
type RefType: RefType;
|
||||||
|
|
||||||
fn cell<F: _ConstMutSwitchUiCallback<Self::RefType>>(&mut self, clojure: &mut F::Clojure<'_>);
|
fn cell(&mut self, scope: impl _ConstMutSwitchUiCallback<Self::RefType>);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) struct ConstMutSwitchUiTableRowImpl<
|
pub(super) struct ConstMutSwitchUiTableRowImpl<
|
||||||
@ -42,13 +44,12 @@ impl<RefType: super::RefType, Constructor: __SwitchUiConstructor1<RefType>> Cons
|
|||||||
{
|
{
|
||||||
type RefType = RefType;
|
type RefType = RefType;
|
||||||
|
|
||||||
fn cell<F: _ConstMutSwitchUiCallback<Self::RefType>>(&mut self, clojure: &mut F::Clojure<'_>) {
|
fn cell(&mut self, cell: impl _ConstMutSwitchUiCallback<Self::RefType>) {
|
||||||
self.row
|
self.row.col(|ui| cell.render(&mut Constructor::__wrap(ui)));
|
||||||
.col(|ui| F::render(&mut Constructor::__wrap(ui), clojure));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
trait __SwitchUiConstructor1<RefType: super::RefType> {
|
pub(super) trait __SwitchUiConstructor1<RefType: super::RefType> {
|
||||||
type Ctx<'a>: ConstMutSwitchUi<RefType = RefType>;
|
type Ctx<'a>: ConstMutSwitchUi<RefType = RefType>;
|
||||||
|
|
||||||
fn __wrap<'a>(ui: &'a mut Ui) -> Self::Ctx<'a>;
|
fn __wrap<'a>(ui: &'a mut Ui) -> Self::Ctx<'a>;
|
||||||
@ -58,53 +59,47 @@ impl __SwitchUiConstructor1<ConstRef> for ConstUI<'_> {
|
|||||||
type Ctx<'a> = ConstUI<'a>;
|
type Ctx<'a> = ConstUI<'a>;
|
||||||
|
|
||||||
fn __wrap<'a>(ui: &'a mut Ui) -> Self::Ctx<'a> {
|
fn __wrap<'a>(ui: &'a mut Ui) -> Self::Ctx<'a> {
|
||||||
todo!()
|
return ConstUI::wrap(ui);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl __SwitchUiConstructor1<MutRef> for MutUI<'_> {
|
impl __SwitchUiConstructor1<MutRef> for MutUI<'_> {
|
||||||
type Ctx<'a> = MutUI<'a>;
|
type Ctx<'a> = MutUI<'a>;
|
||||||
|
|
||||||
fn __wrap<'a>(ui: &'a mut Ui) -> Self::Ctx<'a> {
|
fn __wrap<'a>(ui: &'a mut Ui) -> Self::Ctx<'a> {
|
||||||
todo!()
|
return MutUI::wrap(ui);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn render_table<
|
pub(super) fn render_table<
|
||||||
'a,
|
RefType: super::RefType,
|
||||||
Ctx: ConstMutSwitchUi,
|
Constructor: __SwitchUiConstructor1<RefType>,
|
||||||
F: _ConstMutSwitchUiTableBaseCallback<Ctx::RefType>,
|
|
||||||
Constructor: __SwitchUiConstructor1<Ctx::RefType>,
|
|
||||||
>(
|
>(
|
||||||
ui: &mut Ui,
|
ui: &mut Ui,
|
||||||
vscroll: bool,
|
vscroll: bool,
|
||||||
columnsCount: usize,
|
columnsCount: usize,
|
||||||
headerClojure: &mut <F::Header as _ConstMutSwitchUiTableRowCallback<Ctx::RefType>>::Clojure<'_>,
|
header_render: impl _ConstMutSwitchUiTableHeaderCallback<RefType>,
|
||||||
) {
|
) {
|
||||||
|
let mut rows_it = unsafe { uninitialized() };
|
||||||
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(), columnsCount)
|
||||||
.header(20.0, |row| {
|
.header(20.0, |row| {
|
||||||
F::Header::render_row(
|
rows_it =
|
||||||
&mut ConstMutSwitchUiTableRowImpl::<_, Constructor> {
|
header_render.render_header(&mut ConstMutSwitchUiTableRowImpl::<_, Constructor> {
|
||||||
row,
|
row,
|
||||||
__phantom: PhantomData::default(),
|
__phantom: PhantomData::default(),
|
||||||
},
|
});
|
||||||
headerClojure,
|
|
||||||
)
|
|
||||||
})
|
})
|
||||||
.body(|mut body| {
|
.body(|mut body| {
|
||||||
for mut rowData in F::header_to_body(headerClojure) {
|
rows_it.consume(|row_render| {
|
||||||
body.row(20.0, |row| {
|
body.row(20.0, |row| {
|
||||||
F::Body::render_row(
|
row_render.render_row(&mut ConstMutSwitchUiTableRowImpl::<_, Constructor> {
|
||||||
&mut ConstMutSwitchUiTableRowImpl::<_, Constructor> {
|
|
||||||
row,
|
row,
|
||||||
__phantom: PhantomData::default(),
|
__phantom: PhantomData::default(),
|
||||||
},
|
})
|
||||||
&mut rowData,
|
})
|
||||||
)
|
|
||||||
});
|
});
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,4 @@
|
|||||||
use super::{
|
use super::{_ConstMutSwitchUiTableHeaderCallback, RefType};
|
||||||
_ConstMutSwitchUiTableBaseCallback, _ConstMutSwitchUiTableRowCallback, ConstRef, RefType,
|
|
||||||
};
|
|
||||||
use eframe::emath::Numeric;
|
use eframe::emath::Numeric;
|
||||||
use std::ops::RangeInclusive;
|
use std::ops::RangeInclusive;
|
||||||
|
|
||||||
@ -26,10 +24,7 @@ pub trait ConstMutSwitchUi {
|
|||||||
|
|
||||||
fn space(&mut self);
|
fn space(&mut self);
|
||||||
|
|
||||||
fn horizontal<F: _ConstMutSwitchUiCallback<Self::RefType>>(
|
fn horizontal(&mut self, clojure: impl _ConstMutSwitchUiCallback<Self::RefType>);
|
||||||
&mut self,
|
|
||||||
clojure: &mut F::Clojure<'_>,
|
|
||||||
);
|
|
||||||
|
|
||||||
fn button<T>(
|
fn button<T>(
|
||||||
&mut self,
|
&mut self,
|
||||||
@ -40,29 +35,16 @@ pub trait ConstMutSwitchUi {
|
|||||||
|
|
||||||
fn separator(&mut self);
|
fn separator(&mut self);
|
||||||
|
|
||||||
fn scroll_area_2<F: _ConstMutSwitchUiCallback<Self::RefType>>(
|
fn scroll_area_2(&mut self, clojure: impl _ConstMutSwitchUiCallback<Self::RefType>);
|
||||||
&mut self,
|
|
||||||
clojure: &mut F::Clojure<'_>,
|
|
||||||
);
|
|
||||||
|
|
||||||
fn table<
|
fn table(
|
||||||
'a,
|
|
||||||
F: _ConstMutSwitchUiTableBaseCallback<Self::RefType>
|
|
||||||
>(
|
|
||||||
&mut self,
|
&mut self,
|
||||||
vscroll: bool,
|
vscroll: bool,
|
||||||
columns: usize,
|
columns: usize,
|
||||||
header_clojure: <F::Header as _ConstMutSwitchUiTableRowCallback<Self::RefType>>::Clojure<
|
header: impl _ConstMutSwitchUiTableHeaderCallback<Self::RefType>,
|
||||||
'_,
|
|
||||||
>,
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait _ConstMutSwitchUiCallback<RefType: super::RefType> {
|
pub trait _ConstMutSwitchUiCallback<RefType: super::RefType> {
|
||||||
type Clojure<'a>;
|
fn render(self, ctx: &mut impl ConstMutSwitchUi<RefType = RefType>);
|
||||||
|
|
||||||
fn render<SubCtx: ConstMutSwitchUi<RefType = RefType>>(
|
|
||||||
ctx: &mut SubCtx,
|
|
||||||
clojure: &mut Self::Clojure<'_>,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -10,6 +10,9 @@
|
|||||||
|
|
||||||
Альтернативный вариант - параметризовать тип ссылок...
|
Альтернативный вариант - параметризовать тип ссылок...
|
||||||
|
|
||||||
|
В данном файле приведены только краткие выдержки из рассуждений.
|
||||||
|

|
||||||
|
|
||||||
## 1
|
## 1
|
||||||
|
|
||||||
Начальный интерфейс содержал ассоциированный тип с самой ссылкой и методом
|
Начальный интерфейс содержал ассоциированный тип с самой ссылкой и методом
|
||||||
@ -684,3 +687,151 @@ trait _IteratorGetter {
|
|||||||
|
|
||||||
```
|
```
|
||||||
Но способ работает только для очень простых случаев, так что малопригоден.
|
Но способ работает только для очень простых случаев, так что малопригоден.
|
||||||
|
|
||||||
|
## 5
|
||||||
|
|
||||||
|
Что бы упростить функции, отвечающие за интерфейс и абстрагироваться от формата хранения данных,
|
||||||
|
работа с графом была переделана на контексты (почему-то всё всегда приходит к контекстам):
|
||||||
|
```rust
|
||||||
|
trait Ctx_Graph<G> {
|
||||||
|
type RefType: RefType;
|
||||||
|
|
||||||
|
type Vertex;
|
||||||
|
fn iter_vertices(&mut self, graph: &mut G) -> impl Iterator<Item = Self::Vertex>;
|
||||||
|
|
||||||
|
type Edge;
|
||||||
|
fn iter_edges_or_nothing(
|
||||||
|
&mut self,
|
||||||
|
vertex: &mut Self::Vertex,
|
||||||
|
) -> impl Iterator<Item = 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, state: &mut UpdatePending);
|
||||||
|
}
|
||||||
|
|
||||||
|
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>,
|
||||||
|
) {
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Тип графа передаётся параметром, а не ассоциированным типом, потому что в общем случае
|
||||||
|
контекст может работать с разными представлениями одновременно.
|
||||||
|
|
||||||
|
## 6
|
||||||
|
### 6.1
|
||||||
|
В результате очередной внезапной гениальной мысли, все трейты которые должны были быть
|
||||||
|
лямбдами, вместо ассоциированного типа для параметра теперь используют `self`. Источник
|
||||||
|
озарения - необходимость сделать эту функцию деструктором для передаваемых данных. Не
|
||||||
|
то что бы это нельзя было сделать с параметром, но новое способ оказался удобнее для
|
||||||
|
имплементации:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
trait _ConstMutSwitchUiCallback<RefType: super::RefType> {
|
||||||
|
fn render(self, ctx: &mut impl ConstMutSwitchUi<RefType = RefType>);
|
||||||
|
}
|
||||||
|
|
||||||
|
trait ConstMutSwitchUi {
|
||||||
|
// ...
|
||||||
|
|
||||||
|
fn horizontal<F>(&mut self, clojure: impl _ConstMutSwitchUiCallback<Self::RefType>);
|
||||||
|
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Такой способ более гибок корректен с точки зрения владения переданными для области данными.
|
||||||
|
|
||||||
|
### 6.2
|
||||||
|
Необходимость сделать этот метод деструктором возникла во время оптимизации трейтов для таблиц:
|
||||||
|
метод для отрисовки заголовка становится конвертером в итератор.
|
||||||
|
|
||||||
|
```rust
|
||||||
|
trait _ConstMutSwitchUiTableHeaderCallback<RefType: super::RefType> {
|
||||||
|
type RowRender: _ConstMutSwitchUiTableRowCallback<RefType=RefType>;
|
||||||
|
|
||||||
|
fn render_header<'a>(
|
||||||
|
self,
|
||||||
|
ctx: &mut impl ConstMutSwitchUiTableRow<RefType = RefType>,
|
||||||
|
) -> impl Iterator<Item = Self::RowRender>;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 6.3
|
||||||
|
Итератор, который возвращает значения не может контролировать, что возвращённое значение не будет
|
||||||
|
использоваться после выдачи следующего. Чтобы это ограничить, вместо возврата итератор будет
|
||||||
|
передавать значение в полученную лямбду.
|
||||||
|
|
||||||
|
```rust
|
||||||
|
trait LambdaIterator {
|
||||||
|
type Item;
|
||||||
|
|
||||||
|
fn next<R>(&mut self, receiver: impl FnOnce(Self::Item) -> R) -> Option<R>;
|
||||||
|
|
||||||
|
fn consume(mut self, receiver: impl FnMut(Self::Item)) where Self: Sized {
|
||||||
|
while self.next(|e| receiver(e)).is_some() {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Метод `consume` добавлен просто для удобства. На новый трейт были заменены все итераторы в этом
|
||||||
|
модуле.
|
||||||
|
|
||||||
|
### 6.4
|
||||||
|
Но из-за того, что значение в параметр `self` после `_ConstMutSwitchUiTableHeaderCallback::render_header`
|
||||||
|
не существует, нельзя просто взять и вернуть что-то с ним связанное (вообще должно быть можно, но
|
||||||
|
было много красного и лень разбираться). Решение такое же как и с итератором: "возвращать" в лямбду:
|
||||||
|
```rust
|
||||||
|
trait _ConstMutSwitchUiTableHeaderCallback<RefType: super::RefType> {
|
||||||
|
type RowRender: _ConstMutSwitchUiTableRowCallback<RefType>;
|
||||||
|
type RowsIterator: LambdaIterator<Item = Self::RowRender>;
|
||||||
|
|
||||||
|
fn render_header(
|
||||||
|
self,
|
||||||
|
ctx: &mut impl ConstMutSwitchUiTableRow<RefType = RefType>,
|
||||||
|
render_body: impl FnOnce(Self::RowsIterator),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 6.5
|
||||||
|
Решение передавать в метод отрисовки заголовка лямбду выглядело прекрасно, пока не выяснилось, что
|
||||||
|
для получения дескриптора отрисовки тела таблицы нужно выйти из этого метода, что случается после
|
||||||
|
того как передаётся лямбда которая его использует. Пришлось всё-таки сразиться с borrow checker и найти
|
||||||
|
ошибку, которая мешала возвращать итератор из этого метода и вернуться на этап `6.2`.
|
||||||
|
|
||||||
|
### 6.6
|
||||||
|
Пользоваться контекстом графа внутри лямбды, переданной в итератор от этого контекста по очевидным
|
||||||
|
причинам нельзя, поэтому возвращаемые итераторы были расширены:
|
||||||
|
```rust
|
||||||
|
|
||||||
|
trait Ctx_Graph<G> {
|
||||||
|
// ...
|
||||||
|
|
||||||
|
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>)>;
|
||||||
|
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
```
|
||||||
@ -1,173 +1,201 @@
|
|||||||
use crate::UpdatePending;
|
use crate::gui::const_mut_switch::{
|
||||||
use crate::graph::{CompleteGraph, Edge, EdgesVec, VerticesVec};
|
_ConstMutSwitchUiCallback, _ConstMutSwitchUiTableHeaderCallback,
|
||||||
use crate::gui::const_mut_switch::{_ConstMutSwitchUiCallback, _ConstMutSwitchUiTableBaseCallback, _ConstMutSwitchUiTableRowCallback, ConstMutSwitchUi, ConstMutSwitchUiTableRow, RefGetter, RefType, _IteratorGetter};
|
_ConstMutSwitchUiTableRowCallback, ConstMutSwitchUi, ConstMutSwitchUiTableRow, RefType,
|
||||||
use eframe::egui::{ScrollArea, Ui};
|
};
|
||||||
use egui_extras::{Column, TableBuilder};
|
use crate::{LambdaIterator, UpdatePending};
|
||||||
use std::collections::HashSet;
|
|
||||||
use std::ops::{Index, IndexMut};
|
|
||||||
use std::ptr::NonNull;
|
use std::ptr::NonNull;
|
||||||
|
|
||||||
pub fn draw_lengths_table<'a, Ctx: ConstMutSwitchUi>(
|
pub trait Ctx_Graph<G> {
|
||||||
ctx: &mut Ctx,
|
type RefType: RefType;
|
||||||
graph: <Ctx::RefType as RefType>::Ref<'a, CompleteGraph<()>>,
|
|
||||||
update: <Ctx::RefType as RefType>::Ref<'a, UpdatePending>,
|
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.scroll_area_2::<ScrollArea>(&mut (graph, update));
|
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>,
|
||||||
|
}
|
||||||
|
|
||||||
struct ScrollArea {}
|
impl<G, CtxGraph: Ctx_Graph<G>> _ConstMutSwitchUiCallback<CtxGraph::RefType>
|
||||||
impl<RT: RefType> _ConstMutSwitchUiCallback<RT> for ScrollArea {
|
for ScrollArea<'_, '_, G, CtxGraph>
|
||||||
type Clojure<'a> = (RT::Ref<'a, CompleteGraph<()>>, RT::Ref<'a, UpdatePending>);
|
{
|
||||||
|
fn render(self, ctx: &mut impl ConstMutSwitchUi<RefType=CtxGraph::RefType>) {
|
||||||
fn render<SubCtx: ConstMutSwitchUi<RefType = RT>>(
|
ctx.table(
|
||||||
ctx: &mut SubCtx,
|
false,
|
||||||
mut clojure: &mut (RT::Ref<'_, CompleteGraph<()>>, RT::Ref<'_, UpdatePending>),
|
self.ctx_graph.vertices_count(),
|
||||||
) {
|
Header {
|
||||||
ctx.table::<Table>(false, clojure.0.vertex_count(), HeaderData {
|
ctx_graph: self.ctx_graph,
|
||||||
update_state: clojure.1,
|
graph: self.graph,
|
||||||
edges: CompleteGraph::<()>,
|
update: self.update,
|
||||||
vertices: (),
|
},
|
||||||
})
|
)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Table{}
|
struct Header<'g, 'u, G, CtxGraph: Ctx_Graph<G>> {
|
||||||
impl <RT: RefType>_ConstMutSwitchUiTableBaseCallback<RT> for Table {
|
ctx_graph: &'g mut CtxGraph,
|
||||||
type Header = Header;
|
graph: G,
|
||||||
type Body = Body;
|
update: <CtxGraph::RefType as RefType>::Ref<'u, UpdatePending>,
|
||||||
|
}
|
||||||
|
|
||||||
fn header_to_body<'a>(header: &mut <Self::Header as _ConstMutSwitchUiTableRowCallback<RT>>::Clojure<'a>) -> impl Iterator<Item=<Self::Body as _ConstMutSwitchUiTableRowCallback<RT>>::Clojure<'a>> {
|
impl<'g, 'u, G, CtxGraph: Ctx_Graph<G>> _ConstMutSwitchUiTableHeaderCallback<CtxGraph::RefType>
|
||||||
struct ItGet{};
|
for Header<'g, 'u, G, CtxGraph>
|
||||||
impl _IteratorGetter for ItGet {
|
{
|
||||||
type C = VerticesVec;
|
type RowRender = Row<'g, 'u, G, CtxGraph>;
|
||||||
type T<'a> = HashSet<usize>;
|
|
||||||
|
|
||||||
fn get_const_iterator<'a>(cont: &'a Self::C) -> impl Iterator<Item=&Self::T<'a>> {
|
type RowsIterator = RowsIterators<'g, 'u, G, CtxGraph>;
|
||||||
return cont.iter_indexed()
|
|
||||||
|
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,
|
||||||
|
}
|
||||||
|
|
||||||
fn get_mut_iterator<'a>(cont: &'a mut Self::C) -> impl Iterator<Item=&mut Self::T<'a>> {
|
impl<'g, 'u, G, CtxGraph: Ctx_Graph<G> + 'g> LambdaIterator for RowsIterators<'g, 'u, G, CtxGraph> {
|
||||||
return cont.iter_indexed_mut()
|
type Item = Row<'g, 'u, G, CtxGraph>;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return header.vertices.iter_indexed().enumerate().map(|(ri, (vi, eis))| {
|
fn next<R>(&mut self, receiver: impl FnOnce(Self::Item) -> R) -> Option<R> {
|
||||||
return RowData{
|
return self.vertices.next(|(ctx, v)| {
|
||||||
update_state: header.update_state,
|
self.row_id += 1;
|
||||||
edges: header.edges,
|
return receiver(Row {
|
||||||
row_id: ri,
|
ctx_graph: ctx,
|
||||||
vertex_id: vi,
|
vertex: v,
|
||||||
vertex_edges_ids: eis,
|
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 {}
|
||||||
struct HeaderData<'us, 'es, 'eis, RT: RefType> {
|
impl<RT: RefType> _ConstMutSwitchUiCallback<RT> for CornerCell {
|
||||||
update_state: RT::Ref<'us, UpdatePending>,
|
fn render(self, ctx: &mut impl ConstMutSwitchUi<RefType=RT>) {
|
||||||
edges: RT::Ref<'es, EdgesVec<()>>,
|
|
||||||
vertices: RT::Ref<'eis, VerticesVec>,
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Header {}
|
|
||||||
impl<RT: RefType> _ConstMutSwitchUiTableRowCallback<RT> for Header {
|
|
||||||
type Clojure<'a> = HeaderData<'a, 'a, 'a, RT>;
|
|
||||||
|
|
||||||
fn render_row<Row: ConstMutSwitchUiTableRow<RefType = RT>>(
|
|
||||||
row: &mut Row,
|
|
||||||
clojure: &mut Self::Clojure<'_>,
|
|
||||||
) {
|
|
||||||
row.cell::<CornerCell>(&mut ());
|
|
||||||
for i in 0..clojure.vertices.len() {
|
|
||||||
row.cell::<Title>(&mut (i, NonNull::from_ref(&clojure.update_state)));
|
|
||||||
}
|
|
||||||
|
|
||||||
struct CornerCell {}
|
|
||||||
impl<RT: RefType> _ConstMutSwitchUiCallback<RT> for CornerCell {
|
|
||||||
type Clojure<'a> = ();
|
|
||||||
|
|
||||||
fn render<SubCtx: ConstMutSwitchUi<RefType = RT>>(ctx: &mut SubCtx, _: &mut ()) {
|
|
||||||
ctx.label("#");
|
ctx.label("#");
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct RowData<'us, 'es, 'eis, RT: RefType> {
|
struct TitleCell<'g, 'v, 'rr, 'r: 'rr, G, CtxGraph: Ctx_Graph<G>> {
|
||||||
update_state: RT::Ref<'us, UpdatePending>,
|
ctx_graph: &'g mut CtxGraph,
|
||||||
edges: RT::Ref<'es, EdgesVec<()>>,
|
|
||||||
row_id: usize,
|
row_id: usize,
|
||||||
vertex_id: usize,
|
vertex: &'v CtxGraph::Vertex,
|
||||||
vertex_edges_ids: RT::Ref<'eis, HashSet<usize>>,
|
update: &'rr mut <CtxGraph::RefType as RefType>::Ref<'r, UpdatePending>,
|
||||||
}
|
}
|
||||||
|
impl<G, CtxGraph: Ctx_Graph<G>> _ConstMutSwitchUiCallback<CtxGraph::RefType>
|
||||||
struct Body {}
|
for TitleCell<'_, '_, '_, '_, G, CtxGraph>
|
||||||
impl<RT: RefType> _ConstMutSwitchUiTableRowCallback<RT> for Body {
|
{
|
||||||
type Clojure<'a> = RowData<'a, 'a, 'a, RT>;
|
fn render(self, ctx: &mut impl ConstMutSwitchUi<RefType=CtxGraph::RefType>) {
|
||||||
|
ctx.label(self.row_id.to_string().as_str());
|
||||||
fn render_row<Row: ConstMutSwitchUiTableRow<RefType = RT>>(
|
ctx.button("-", self.update, |s| {
|
||||||
row: &mut Row,
|
self.ctx_graph.set_vertex_to_update_state(self.vertex, s)
|
||||||
clojure: &mut Self::Clojure<'_>,
|
});
|
||||||
) {
|
|
||||||
row.cell::<Title>(&mut (clojure.row_id, NonNull::from_ref(&clojure.update_state)));
|
|
||||||
|
|
||||||
// not map because a borrow checker doesn't allow returning from lambda.
|
|
||||||
// raw pointer because a borrow checker.
|
|
||||||
let mut local_edges =
|
|
||||||
Vec::<(usize, NonNull<f64>)>::with_capacity(clojure.vertex_edges_ids.len());
|
|
||||||
for ei in clojure.vertex_edges_ids.iter() {
|
|
||||||
let mut e = RT::_get(
|
|
||||||
&mut clojure.edges,
|
|
||||||
|ee| ee.index(*ei),
|
|
||||||
|ee| ee.index_mut(*ei),
|
|
||||||
);
|
|
||||||
let another_vertex = e.another(clojure.vertex_id);
|
|
||||||
let length_storage = RT::_get(&mut e, |e| &e.length, |e| &mut e.length);
|
|
||||||
let length_storage = unsafe { RT::_to_ptr(length_storage) };
|
|
||||||
local_edges.push((another_vertex, length_storage));
|
|
||||||
}
|
|
||||||
local_edges.sort_by_key(|(k, _)| *k);
|
|
||||||
|
|
||||||
for (column_index, cell_data) in local_edges.iter_mut().enumerate() {
|
|
||||||
if (column_index == clojure.row_id) {
|
|
||||||
row.cell::<EmptyCell>(&mut ());
|
|
||||||
}
|
|
||||||
row.cell::<Cell>(&mut unsafe { RT::_from_ptr(cell_data.1) });
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Cell {}
|
|
||||||
impl<RT: RefType> _ConstMutSwitchUiCallback<RT> for Cell {
|
|
||||||
type Clojure<'a> = RT::Ref<'a, f64>;
|
|
||||||
|
|
||||||
fn render<SubCtx: ConstMutSwitchUi<RefType = RT>>(
|
|
||||||
ctx: &mut SubCtx,
|
|
||||||
clojure: &mut Self::Clojure<'_>,
|
|
||||||
) {
|
|
||||||
ctx.slider(0.0..=10.0, 0.1, clojure);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct EmptyCell {}
|
|
||||||
impl<RT: RefType> _ConstMutSwitchUiCallback<RT> for EmptyCell {
|
|
||||||
type Clojure<'a> = ();
|
|
||||||
|
|
||||||
fn render<SubCtx: ConstMutSwitchUi<RefType = RT>>(_: &mut SubCtx, _: &mut ()) {}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Title {}
|
struct LengthCell<'rr, 'r: 'rr, RT: RefType> {
|
||||||
impl<RT: RefType> _ConstMutSwitchUiCallback<RT> for Title {
|
length: &'rr mut RT::Ref<'r, f64>,
|
||||||
type Clojure<'a> = (usize, NonNull<RT::Ref<'a, UpdatePending>>);
|
}
|
||||||
|
impl<RT: RefType> _ConstMutSwitchUiCallback<RT> for LengthCell<'_, '_, RT> {
|
||||||
fn render<SubCtx: ConstMutSwitchUi<RefType = RT>>(
|
fn render(self, ctx: &mut impl ConstMutSwitchUi<RefType=RT>) {
|
||||||
ctx: &mut SubCtx,
|
ctx.slider(0.0..=10.0, 0.1, self.length);
|
||||||
clojure: &mut Self::Clojure<'_>,
|
|
||||||
) {
|
|
||||||
ctx.label(clojure.0.to_string().as_str());
|
|
||||||
ctx.button("-", unsafe { clojure.1.as_mut() }, |s| {
|
|
||||||
*s = UpdatePending::Remove(clojure.0)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct EmptyCell {}
|
||||||
|
impl<RT: RefType> _ConstMutSwitchUiCallback<RT> for EmptyCell {
|
||||||
|
fn render(self, _: &mut impl ConstMutSwitchUi<RefType=RT>) {}
|
||||||
|
}
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
use crate::graph::{Edge, EdgesVec, VerticesVec};
|
use crate::graph::{Edge, EdgesVec, VerticesVec};
|
||||||
use eframe::egui;
|
use eframe::egui;
|
||||||
use eframe::egui::{Align2, Color32, FontDefinitions, Pos2, Rect, StrokeKind, Ui, Vec2};
|
use eframe::egui::{Align2, Color32, Pos2, Rect, StrokeKind, Ui, Vec2};
|
||||||
use eframe::epaint::{CornerRadius, Stroke};
|
use eframe::epaint::{CornerRadius, Stroke};
|
||||||
|
|
||||||
pub fn render_graph<D>(
|
pub fn render_graph<D>(
|
||||||
|
|||||||
28
utility/src/lambda_iterator.rs
Normal file
28
utility/src/lambda_iterator.rs
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
pub trait LambdaIterator {
|
||||||
|
type Item;
|
||||||
|
|
||||||
|
fn next<R>(&mut self, receiver: impl FnOnce(Self::Item) -> R) -> Option<R>;
|
||||||
|
|
||||||
|
fn consume(mut self, mut receiver: impl FnMut(Self::Item))
|
||||||
|
where
|
||||||
|
Self: Sized,
|
||||||
|
{
|
||||||
|
while self.next(|e| receiver(e)).is_some() {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn make_lambda<I: Iterator>(it: I) -> impl LambdaIterator<Item = I::Item> {
|
||||||
|
return LambdaIteratorConverter { it };
|
||||||
|
}
|
||||||
|
|
||||||
|
struct LambdaIteratorConverter<I: Iterator> {
|
||||||
|
it: I,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<I: Iterator> LambdaIterator for LambdaIteratorConverter<I> {
|
||||||
|
type Item = I::Item;
|
||||||
|
|
||||||
|
fn next<R>(&mut self, receiver: impl FnOnce(Self::Item) -> R) -> Option<R> {
|
||||||
|
return self.it.next().map(receiver);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,7 +1,9 @@
|
|||||||
pub mod graph;
|
pub mod graph;
|
||||||
pub mod gui;
|
pub mod gui;
|
||||||
|
mod lambda_iterator;
|
||||||
mod update_pending;
|
mod update_pending;
|
||||||
mod weighted_random;
|
mod weighted_random;
|
||||||
|
|
||||||
|
pub use lambda_iterator::{LambdaIterator, make_lambda};
|
||||||
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