mirror of
https://github.com/danbulant/cushy
synced 2026-06-18 14:01:10 +00:00
Refs #98 This refactor overhauls the reactive system to move all the reactive methods to traits. The side effect of this change is that now DynamicReader's API is the same as Dynamic's API, but because it only implements Source<T>, DynamicReader does not offer any mutation functions. While it's unfortunate to have more traits to include to use Cushy, this seems like the best option, and it offers a path to try to integrate this into the tuple ForEach/MapEach traits. Unfortunately, my attempt at doing those in this set of changes led to issues specifying generic associated lifetimes for the DynamicGuard. But, I was also in the middle of this larger refactoring, so it might be that a fresh attempt will succeed.
109 lines
3 KiB
Rust
109 lines
3 KiB
Rust
use cushy::animation::{LinearInterpolate, PercentBetween};
|
|
use cushy::value::{Destination, Dynamic, ForEach, Source};
|
|
use cushy::widget::MakeWidget;
|
|
use cushy::widgets::checkbox::Checkable;
|
|
use cushy::widgets::input::InputValue;
|
|
use cushy::widgets::slider::Slidable;
|
|
use cushy::Run;
|
|
use figures::units::Lp;
|
|
use figures::Ranged;
|
|
|
|
fn main() -> cushy::Result {
|
|
let enabled = Dynamic::new(true);
|
|
u8_slider()
|
|
.and(u8_range_slider())
|
|
.and(enum_slider())
|
|
.into_rows()
|
|
.with_enabled(enabled.clone())
|
|
.and(enabled.into_checkbox("Enabled"))
|
|
.into_rows()
|
|
.expand_horizontally()
|
|
.contain()
|
|
.width(..Lp::points(800))
|
|
.pad()
|
|
.centered()
|
|
.run()
|
|
}
|
|
|
|
fn u8_slider() -> impl MakeWidget {
|
|
let min = Dynamic::new(u8::MIN);
|
|
let min_text = min.linked_string();
|
|
let max = Dynamic::new(u8::MAX);
|
|
let max_text = max.linked_string();
|
|
let value = Dynamic::new(128_u8);
|
|
let value_text = value.map_each(ToString::to_string);
|
|
|
|
"Min"
|
|
.and(min_text.into_input())
|
|
.and("Max")
|
|
.and(max_text.into_input())
|
|
.into_columns()
|
|
.centered()
|
|
.and(value.slider_between(min, max))
|
|
.and(value_text.centered())
|
|
.into_rows()
|
|
}
|
|
|
|
fn u8_range_slider() -> impl MakeWidget {
|
|
let range = Dynamic::new(42..=127);
|
|
let start = range.map_each(|range| *range.start());
|
|
let end = range.map_each(|range| *range.end());
|
|
range.set_source((&start, &end).for_each({
|
|
let range = range.clone();
|
|
move |(start, end)| {
|
|
range.set(*start..=*end);
|
|
}
|
|
}));
|
|
|
|
let min = Dynamic::new(u8::MIN);
|
|
let min_text = min.linked_string();
|
|
let start_text = start.linked_string();
|
|
let end_text = end.linked_string();
|
|
let max = Dynamic::new(u8::MAX);
|
|
let max_text = max.linked_string();
|
|
let value_text = range.map_each(|r| format!("{}..={}", r.start(), r.end()));
|
|
|
|
"Min"
|
|
.and(min_text.into_input())
|
|
.and("Start")
|
|
.and(start_text.into_input())
|
|
.and("End")
|
|
.and(end_text.into_input())
|
|
.and("Max")
|
|
.and(max_text.into_input())
|
|
.into_columns()
|
|
.centered()
|
|
.and(range.slider_between(min, max))
|
|
.and(value_text.centered())
|
|
.into_rows()
|
|
}
|
|
|
|
#[derive(LinearInterpolate, Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd)]
|
|
enum SlidableEnum {
|
|
A,
|
|
B,
|
|
C,
|
|
}
|
|
|
|
impl PercentBetween for SlidableEnum {
|
|
fn percent_between(&self, min: &Self, max: &Self) -> cushy::animation::ZeroToOne {
|
|
let min = *min as u8;
|
|
let max = *max as u8;
|
|
let value = *self as u8;
|
|
value.percent_between(&min, &max)
|
|
}
|
|
}
|
|
|
|
impl Ranged for SlidableEnum {
|
|
const MAX: Self = Self::C;
|
|
const MIN: Self = Self::A;
|
|
}
|
|
|
|
fn enum_slider() -> impl MakeWidget {
|
|
let enum_value = Dynamic::new(SlidableEnum::A);
|
|
let enum_text = enum_value.map_each(|value| format!("{value:?}"));
|
|
"Custom Enum"
|
|
.and(enum_value.slider())
|
|
.and(enum_text)
|
|
.into_rows()
|
|
}
|