@@ -57,6 +57,44 @@ pub trait Lens<T: ?Sized, U: ?Sized> {
57
57
fn with_mut < V , F : FnOnce ( & mut U ) -> V > ( & self , data : & mut T , f : F ) -> V ;
58
58
}
59
59
60
+ /// Helpers for manipulating `Lens`es
61
+ pub trait LensExt < A : ?Sized , B : ?Sized > : Lens < A , B > {
62
+ /// Copy the targeted value out of `data`
63
+ fn get ( & self , data : & A ) -> B
64
+ where
65
+ B : Clone ,
66
+ {
67
+ self . with ( data, |x| x. clone ( ) )
68
+ }
69
+
70
+ /// Set the targeted value in `data` to `value`
71
+ fn put ( & self , data : & mut A , value : B )
72
+ where
73
+ B : Sized ,
74
+ {
75
+ self . with_mut ( data, |x| * x = value) ;
76
+ }
77
+
78
+ /// Compose a `Lens<A, B>` with a `Lens<B, C>` to produce a `Lens<A, C>`
79
+ ///
80
+ /// ```
81
+ /// # use druid::*;
82
+ /// struct Foo { x: (u32, bool) }
83
+ /// let lens = lens!(Foo, x).then(lens!((u32, bool), 1));
84
+ /// assert_eq!(lens.get(&Foo { x: (0, true) }), true);
85
+ /// ```
86
+ fn then < Other , C > ( self , other : Other ) -> Then < Self , Other , B >
87
+ where
88
+ Other : Lens < B , C > + Sized ,
89
+ C : ?Sized ,
90
+ Self : Sized ,
91
+ {
92
+ Then :: new ( self , other)
93
+ }
94
+ }
95
+
96
+ impl < A : ?Sized , B : ?Sized , T : Lens < A , B > > LensExt < A , B > for T { }
97
+
60
98
// A case can be made this should be in the `widget` module.
61
99
62
100
/// A wrapper for its widget subtree to have access to a part
@@ -147,7 +185,7 @@ where
147
185
/// See also the `lens` macro.
148
186
///
149
187
/// ```
150
- /// let lens = druid::Field::new(|x: &Vec<u32>| &x[42], |x| &mut x[42]);
188
+ /// let lens = druid::lens:: Field::new(|x: &Vec<u32>| &x[42], |x| &mut x[42]);
151
189
/// ```
152
190
pub struct Field < Get , GetMut > {
153
191
get : Get ,
@@ -194,9 +232,61 @@ where
194
232
#[ macro_export]
195
233
macro_rules! lens {
196
234
( $ty: ty, [ $index: expr] ) => {
197
- $crate:: Field :: new:: <$ty, _>( |x| & x[ $index] , |x| & mut x[ $index] )
235
+ $crate:: lens :: Field :: new:: <$ty, _>( |x| & x[ $index] , |x| & mut x[ $index] )
198
236
} ;
199
237
( $ty: ty, $field: tt) => {
200
- $crate:: Field :: new:: <$ty, _>( |x| & x. $field, |x| & mut x. $field)
238
+ $crate:: lens :: Field :: new:: <$ty, _>( |x| & x. $field, |x| & mut x. $field)
201
239
} ;
202
240
}
241
+
242
+ /// `Lens` composed of two lenses joined together
243
+ #[ derive( Debug , Copy ) ]
244
+ pub struct Then < T , U , B : ?Sized > {
245
+ left : T ,
246
+ right : U ,
247
+ _marker : PhantomData < B > ,
248
+ }
249
+
250
+ impl < T , U , B : ?Sized > Then < T , U , B > {
251
+ /// Compose two lenses
252
+ ///
253
+ /// See also `LensExt::then`.
254
+ pub fn new < A : ?Sized , C : ?Sized > ( left : T , right : U ) -> Self
255
+ where
256
+ T : Lens < A , B > ,
257
+ U : Lens < B , C > ,
258
+ {
259
+ Self {
260
+ left,
261
+ right,
262
+ _marker : PhantomData ,
263
+ }
264
+ }
265
+ }
266
+
267
+ impl < T , U , A , B , C > Lens < A , C > for Then < T , U , B >
268
+ where
269
+ A : ?Sized ,
270
+ B : ?Sized ,
271
+ C : ?Sized ,
272
+ T : Lens < A , B > ,
273
+ U : Lens < B , C > ,
274
+ {
275
+ fn with < V , F : FnOnce ( & C ) -> V > ( & self , data : & A , f : F ) -> V {
276
+ self . left . with ( data, |b| self . right . with ( b, f) )
277
+ }
278
+
279
+ fn with_mut < V , F : FnOnce ( & mut C ) -> V > ( & self , data : & mut A , f : F ) -> V {
280
+ self . left . with_mut ( data, |b| self . right . with_mut ( b, f) )
281
+ }
282
+ }
283
+
284
+ impl < T : Clone , U : Clone , B > Clone for Then < T , U , B > {
285
+ fn clone ( & self ) -> Self {
286
+ Self {
287
+ left : self . left . clone ( ) ,
288
+ right : self . right . clone ( ) ,
289
+ _marker : PhantomData ,
290
+ }
291
+ }
292
+ }
0 commit comments