use std::marker::PhantomData;
use std::ops;
use std::sync::Arc;
use crate::kurbo::Size;
use crate::widget::prelude::*;
use crate::Data;
pub trait Lens<T: ?Sized, U: ?Sized> {
fn with<V, F: FnOnce(&U) -> V>(&self, data: &T, f: F) -> V;
fn with_mut<V, F: FnOnce(&mut U) -> V>(&self, data: &mut T, f: F) -> V;
}
pub trait LensExt<A: ?Sized, B: ?Sized>: Lens<A, B> {
fn get(&self, data: &A) -> B
where
B: Clone,
{
self.with(data, |x| x.clone())
}
fn put(&self, data: &mut A, value: B)
where
B: Sized,
{
self.with_mut(data, |x| *x = value);
}
fn then<Other, C>(self, other: Other) -> Then<Self, Other, B>
where
Other: Lens<B, C> + Sized,
C: ?Sized,
Self: Sized,
{
Then::new(self, other)
}
fn map<Get, Put, C>(self, get: Get, put: Put) -> Then<Self, Map<Get, Put>, B>
where
Get: Fn(&B) -> C,
Put: Fn(&mut B, C),
Self: Sized,
{
self.then(Map::new(get, put))
}
fn deref(self) -> Then<Self, Deref, B>
where
B: ops::Deref + ops::DerefMut,
Self: Sized,
{
self.then(Deref)
}
fn index<I>(self, index: I) -> Then<Self, Index<I>, B>
where
I: Clone,
B: ops::Index<I> + ops::IndexMut<I>,
Self: Sized,
{
self.then(Index::new(index))
}
fn in_arc(self) -> InArc<Self>
where
A: Clone,
B: Data,
Self: Sized,
{
InArc::new(self)
}
}
impl<A: ?Sized, B: ?Sized, T: Lens<A, B>> LensExt<A, B> for T {}
pub struct LensWrap<U, L, W> {
inner: W,
lens: L,
phantom: PhantomData<U>,
}
impl<U, L, W> LensWrap<U, L, W> {
pub fn new(inner: W, lens: L) -> LensWrap<U, L, W> {
LensWrap {
inner,
lens,
phantom: Default::default(),
}
}
}
impl<T, U, L, W> Widget<T> for LensWrap<U, L, W>
where
T: Data,
U: Data,
L: Lens<T, U>,
W: Widget<U>,
{
fn event(&mut self, ctx: &mut EventCtx, event: &Event, data: &mut T, env: &Env) {
let inner = &mut self.inner;
self.lens
.with_mut(data, |data| inner.event(ctx, event, data, env))
}
fn lifecycle(&mut self, ctx: &mut LifeCycleCtx, event: &LifeCycle, data: &T, env: &Env) {
let inner = &mut self.inner;
self.lens
.with(data, |data| inner.lifecycle(ctx, event, data, env))
}
fn update(&mut self, ctx: &mut UpdateCtx, old_data: &T, data: &T, env: &Env) {
let inner = &mut self.inner;
let lens = &self.lens;
lens.with(old_data, |old_data| {
lens.with(data, |data| {
if !old_data.same(data) {
inner.update(ctx, old_data, data, env);
}
})
})
}
fn layout(&mut self, ctx: &mut LayoutCtx, bc: &BoxConstraints, data: &T, env: &Env) -> Size {
let inner = &mut self.inner;
self.lens
.with(data, |data| inner.layout(ctx, bc, data, env))
}
fn paint(&mut self, ctx: &mut PaintCtx, data: &T, env: &Env) {
let inner = &mut self.inner;
self.lens.with(data, |data| inner.paint(ctx, data, env));
}
fn id(&self) -> Option<WidgetId> {
self.inner.id()
}
}
pub struct Field<Get, GetMut> {
get: Get,
get_mut: GetMut,
}
impl<Get, GetMut> Field<Get, GetMut> {
pub fn new<T: ?Sized, U: ?Sized>(get: Get, get_mut: GetMut) -> Self
where
Get: Fn(&T) -> &U,
GetMut: Fn(&mut T) -> &mut U,
{
Self { get, get_mut }
}
}
impl<T, U, Get, GetMut> Lens<T, U> for Field<Get, GetMut>
where
T: ?Sized,
U: ?Sized,
Get: Fn(&T) -> &U,
GetMut: Fn(&mut T) -> &mut U,
{
fn with<V, F: FnOnce(&U) -> V>(&self, data: &T, f: F) -> V {
f((self.get)(data))
}
fn with_mut<V, F: FnOnce(&mut U) -> V>(&self, data: &mut T, f: F) -> V {
f((self.get_mut)(data))
}
}
#[macro_export]
macro_rules! lens {
($ty:ty, [$index:expr]) => {
$crate::lens::Field::new::<$ty, _>(|x| &x[$index], |x| &mut x[$index])
};
($ty:ty, $field:tt) => {
$crate::lens::Field::new::<$ty, _>(|x| &x.$field, |x| &mut x.$field)
};
}
#[derive(Debug, Copy)]
pub struct Then<T, U, B: ?Sized> {
left: T,
right: U,
_marker: PhantomData<B>,
}
impl<T, U, B: ?Sized> Then<T, U, B> {
pub fn new<A: ?Sized, C: ?Sized>(left: T, right: U) -> Self
where
T: Lens<A, B>,
U: Lens<B, C>,
{
Self {
left,
right,
_marker: PhantomData,
}
}
}
impl<T, U, A, B, C> Lens<A, C> for Then<T, U, B>
where
A: ?Sized,
B: ?Sized,
C: ?Sized,
T: Lens<A, B>,
U: Lens<B, C>,
{
fn with<V, F: FnOnce(&C) -> V>(&self, data: &A, f: F) -> V {
self.left.with(data, |b| self.right.with(b, f))
}
fn with_mut<V, F: FnOnce(&mut C) -> V>(&self, data: &mut A, f: F) -> V {
self.left.with_mut(data, |b| self.right.with_mut(b, f))
}
}
impl<T: Clone, U: Clone, B> Clone for Then<T, U, B> {
fn clone(&self) -> Self {
Self {
left: self.left.clone(),
right: self.right.clone(),
_marker: PhantomData,
}
}
}
#[derive(Debug, Copy, Clone)]
pub struct Map<Get, Put> {
get: Get,
put: Put,
}
impl<Get, Put> Map<Get, Put> {
pub fn new<A: ?Sized, B>(get: Get, put: Put) -> Self
where
Get: Fn(&A) -> B,
Put: Fn(&mut A, B),
{
Self { get, put }
}
}
impl<A: ?Sized, B, Get, Put> Lens<A, B> for Map<Get, Put>
where
Get: Fn(&A) -> B,
Put: Fn(&mut A, B),
{
fn with<V, F: FnOnce(&B) -> V>(&self, data: &A, f: F) -> V {
f(&(self.get)(data))
}
fn with_mut<V, F: FnOnce(&mut B) -> V>(&self, data: &mut A, f: F) -> V {
let mut temp = (self.get)(data);
let x = f(&mut temp);
(self.put)(data, temp);
x
}
}
#[derive(Debug, Copy, Clone)]
pub struct Deref;
impl<T: ?Sized> Lens<T, T::Target> for Deref
where
T: ops::Deref + ops::DerefMut,
{
fn with<V, F: FnOnce(&T::Target) -> V>(&self, data: &T, f: F) -> V {
f(data.deref())
}
fn with_mut<V, F: FnOnce(&mut T::Target) -> V>(&self, data: &mut T, f: F) -> V {
f(data.deref_mut())
}
}
#[derive(Debug, Copy, Clone)]
pub struct Index<I> {
index: I,
}
impl<I> Index<I> {
pub fn new(index: I) -> Self {
Self { index }
}
}
impl<T, I> Lens<T, T::Output> for Index<I>
where
T: ?Sized + ops::Index<I> + ops::IndexMut<I>,
I: Clone,
{
fn with<V, F: FnOnce(&T::Output) -> V>(&self, data: &T, f: F) -> V {
f(&data[self.index.clone()])
}
fn with_mut<V, F: FnOnce(&mut T::Output) -> V>(&self, data: &mut T, f: F) -> V {
f(&mut data[self.index.clone()])
}
}
#[derive(Debug, Copy, Clone)]
pub struct Id;
impl<A: ?Sized> Lens<A, A> for Id {
fn with<V, F: FnOnce(&A) -> V>(&self, data: &A, f: F) -> V {
f(data)
}
fn with_mut<V, F: FnOnce(&mut A) -> V>(&self, data: &mut A, f: F) -> V {
f(data)
}
}
#[derive(Debug, Copy, Clone)]
pub struct InArc<L> {
inner: L,
}
impl<L> InArc<L> {
pub fn new<A, B>(inner: L) -> Self
where
A: Clone,
B: Data,
L: Lens<A, B>,
{
Self { inner }
}
}
impl<A, B, L> Lens<Arc<A>, B> for InArc<L>
where
A: Clone,
B: Data,
L: Lens<A, B>,
{
fn with<V, F: FnOnce(&B) -> V>(&self, data: &Arc<A>, f: F) -> V {
self.inner.with(data, f)
}
fn with_mut<V, F: FnOnce(&mut B) -> V>(&self, data: &mut Arc<A>, f: F) -> V {
let mut temp = self.inner.with(data, |x| x.clone());
let v = f(&mut temp);
if self.inner.with(data, |x| !x.same(&temp)) {
self.inner.with_mut(Arc::make_mut(data), |x| *x = temp);
}
v
}
}